Annotation of sys/dev/ic/sili.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: sili.c,v 1.33 2007/04/22 00:06:51 dlg Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: #include <sys/param.h>
! 20: #include <sys/systm.h>
! 21: #include <sys/buf.h>
! 22: #include <sys/device.h>
! 23: #include <sys/proc.h>
! 24: #include <sys/malloc.h>
! 25: #include <sys/kernel.h>
! 26:
! 27: #include <machine/bus.h>
! 28:
! 29: #include <dev/ata/atascsi.h>
! 30:
! 31: #include <dev/ic/silireg.h>
! 32: #include <dev/ic/silivar.h>
! 33:
! 34: /* use SILI_DEBUG for dmesg spam */
! 35: #define NO_SILI_DEBUG
! 36:
! 37: #ifdef SILI_DEBUG
! 38: #define SILI_D_VERBOSE (1<<0)
! 39: #define SILI_D_INTR (1<<1)
! 40:
! 41: int silidebug = SILI_D_VERBOSE;
! 42:
! 43: #define DPRINTF(m, a...) do { if ((m) & silidebug) printf(a); } while (0)
! 44: #else
! 45: #define DPRINTF(m, a...)
! 46: #endif
! 47:
! 48: struct cfdriver sili_cd = {
! 49: NULL, "sili", DV_DULL
! 50: };
! 51:
! 52: /* wrapper around dma memory */
! 53: struct sili_dmamem {
! 54: bus_dmamap_t sdm_map;
! 55: bus_dma_segment_t sdm_seg;
! 56: size_t sdm_size;
! 57: caddr_t sdm_kva;
! 58: };
! 59: #define SILI_DMA_MAP(_sdm) ((_sdm)->sdm_map)
! 60: #define SILI_DMA_DVA(_sdm) ((_sdm)->sdm_map->dm_segs[0].ds_addr)
! 61: #define SILI_DMA_KVA(_sdm) ((void *)(_sdm)->sdm_kva)
! 62:
! 63: struct sili_dmamem *sili_dmamem_alloc(struct sili_softc *, bus_size_t,
! 64: bus_size_t);
! 65: void sili_dmamem_free(struct sili_softc *,
! 66: struct sili_dmamem *);
! 67:
! 68: /* per port goo */
! 69: struct sili_ccb;
! 70:
! 71: /* size of scratch space for use in error recovery. */
! 72: #define SILI_SCRATCH_LEN 512 /* must be at least 1 sector */
! 73:
! 74: struct sili_port {
! 75: struct sili_softc *sp_sc;
! 76: bus_space_handle_t sp_ioh;
! 77:
! 78: struct sili_ccb *sp_ccbs;
! 79: struct sili_dmamem *sp_cmds;
! 80: struct sili_dmamem *sp_scratch;
! 81:
! 82: TAILQ_HEAD(, sili_ccb) sp_free_ccbs;
! 83:
! 84: volatile u_int32_t sp_active;
! 85: TAILQ_HEAD(, sili_ccb) sp_active_ccbs;
! 86: TAILQ_HEAD(, sili_ccb) sp_deferred_ccbs;
! 87:
! 88: #ifdef SILI_DEBUG
! 89: char sp_name[16];
! 90: #define PORTNAME(_sp) ((_sp)->sp_name)
! 91: #else
! 92: #define PORTNAME(_sp) DEVNAME((_sp)->sp_sc)
! 93: #endif
! 94: };
! 95:
! 96: int sili_ports_alloc(struct sili_softc *);
! 97: void sili_ports_free(struct sili_softc *);
! 98:
! 99: /* ccb shizz */
! 100:
! 101: /*
! 102: * the dma memory for each command will be made up of a prb followed by
! 103: * 7 sgts, this is a neat 512 bytes.
! 104: */
! 105: #define SILI_CMD_LEN 512
! 106:
! 107: /*
! 108: * you can fit 22 sge's into 7 sgts and a prb:
! 109: * there's 1 sgl in an atapi prb (two in the ata one, but we cant over
! 110: * advertise), but that's needed for the chain element. you get three sges
! 111: * per sgt cos you lose the 4th sge for the chaining, but you keep it in
! 112: * the last sgt. so 3 x 6 + 4 is 22.
! 113: */
! 114: #define SILI_DMA_SEGS 22
! 115:
! 116: struct sili_ccb {
! 117: struct ata_xfer ccb_xa;
! 118:
! 119: void *ccb_cmd;
! 120: u_int64_t ccb_cmd_dva;
! 121: bus_dmamap_t ccb_dmamap;
! 122:
! 123: struct sili_port *ccb_port;
! 124:
! 125: TAILQ_ENTRY(sili_ccb) ccb_entry;
! 126: };
! 127:
! 128: int sili_ccb_alloc(struct sili_port *);
! 129: void sili_ccb_free(struct sili_port *);
! 130: struct sili_ccb *sili_get_ccb(struct sili_port *);
! 131: void sili_put_ccb(struct sili_ccb *);
! 132:
! 133: /* bus space ops */
! 134: u_int32_t sili_read(struct sili_softc *, bus_size_t);
! 135: void sili_write(struct sili_softc *, bus_size_t, u_int32_t);
! 136: u_int32_t sili_pread(struct sili_port *, bus_size_t);
! 137: void sili_pwrite(struct sili_port *, bus_size_t, u_int32_t);
! 138: int sili_pwait_eq(struct sili_port *, bus_size_t,
! 139: u_int32_t, u_int32_t, int);
! 140: int sili_pwait_ne(struct sili_port *, bus_size_t,
! 141: u_int32_t, u_int32_t, int);
! 142:
! 143: /* command handling */
! 144: void sili_post_direct(struct sili_port *, u_int,
! 145: void *, size_t buflen);
! 146: void sili_post_indirect(struct sili_port *,
! 147: struct sili_ccb *);
! 148: void sili_pread_fis(struct sili_port *, u_int,
! 149: struct ata_fis_d2h *);
! 150: u_int32_t sili_signature(struct sili_port *, u_int);
! 151: int sili_load(struct sili_ccb *, struct sili_sge *, int);
! 152: void sili_unload(struct sili_ccb *);
! 153: int sili_poll(struct sili_ccb *, int, void (*)(void *));
! 154: void sili_start(struct sili_port *, struct sili_ccb *);
! 155: int sili_read_ncq_error(struct sili_port *, int *);
! 156:
! 157: /* port interrupt handler */
! 158: u_int32_t sili_port_intr(struct sili_port *, int);
! 159:
! 160: /* atascsi interface */
! 161: int sili_ata_probe(void *, int);
! 162: struct ata_xfer *sili_ata_get_xfer(void *, int);
! 163: void sili_ata_put_xfer(struct ata_xfer *);
! 164: int sili_ata_cmd(struct ata_xfer *);
! 165:
! 166: struct atascsi_methods sili_atascsi_methods = {
! 167: sili_ata_probe,
! 168: sili_ata_get_xfer,
! 169: sili_ata_cmd
! 170: };
! 171:
! 172: /* completion paths */
! 173: void sili_ata_cmd_done(struct sili_ccb *, int);
! 174: void sili_ata_cmd_timeout(void *);
! 175:
! 176: int
! 177: sili_attach(struct sili_softc *sc)
! 178: {
! 179: struct atascsi_attach_args aaa;
! 180:
! 181: printf("\n");
! 182:
! 183: if (sili_ports_alloc(sc) != 0) {
! 184: /* error already printed by sili_port_alloc */
! 185: return (1);
! 186: }
! 187:
! 188: /* bounce the controller */
! 189: sili_write(sc, SILI_REG_GC, SILI_REG_GC_GR);
! 190: sili_write(sc, SILI_REG_GC, 0x0);
! 191:
! 192: bzero(&aaa, sizeof(aaa));
! 193: aaa.aaa_cookie = sc;
! 194: aaa.aaa_methods = &sili_atascsi_methods;
! 195: aaa.aaa_minphys = minphys;
! 196: aaa.aaa_nports = sc->sc_nports;
! 197: aaa.aaa_ncmds = SILI_MAX_CMDS;
! 198: aaa.aaa_capability = ASAA_CAP_NCQ;
! 199:
! 200: sc->sc_atascsi = atascsi_attach(&sc->sc_dev, &aaa);
! 201:
! 202: return (0);
! 203: }
! 204:
! 205: int
! 206: sili_detach(struct sili_softc *sc, int flags)
! 207: {
! 208: return (0);
! 209: }
! 210:
! 211: u_int32_t
! 212: sili_port_intr(struct sili_port *sp, int timeout_slot)
! 213: {
! 214: u_int32_t is, pss_saved, pss_masked;
! 215: u_int32_t processed = 0, need_restart = 0;
! 216: int slot;
! 217: struct sili_ccb *ccb;
! 218:
! 219: is = sili_pread(sp, SILI_PREG_IS);
! 220: pss_saved = sili_pread(sp, SILI_PREG_PSS); /* reading acks CMDCOMP */
! 221:
! 222: #ifdef SILI_DEBUG
! 223: if ((pss_saved & SILI_PREG_PSS_ALL_SLOTS) != sp->sp_active ||
! 224: ((is >> 16) & ~SILI_PREG_IS_CMDCOMP)) {
! 225: DPRINTF(SILI_D_INTR, "%s: IS: 0x%08x (0x%b), PSS: %08x, "
! 226: "active: %08x\n", PORTNAME(sp), is, is >> 16, SILI_PFMT_IS,
! 227: pss_saved, sp->sp_active);
! 228: }
! 229: #endif
! 230:
! 231: /* Only interested in slot status bits. */
! 232: pss_saved &= SILI_PREG_PSS_ALL_SLOTS;
! 233:
! 234: if (is & SILI_PREG_IS_CMDERR) {
! 235: int err_slot, err_code;
! 236: u_int32_t sactive = 0;
! 237:
! 238: sili_pwrite(sp, SILI_PREG_IS, SILI_PREG_IS_CMDERR);
! 239: err_slot = SILI_PREG_PCS_ACTIVE(sili_pread(sp, SILI_PREG_PCS));
! 240: err_code = sili_pread(sp, SILI_PREG_CE);
! 241: ccb = &sp->sp_ccbs[err_slot];
! 242:
! 243: switch (err_code) {
! 244: case SILI_PREG_CE_DEVICEERROR:
! 245: case SILI_PREG_CE_DATAFISERROR:
! 246: /* Extract error from command slot in LRAM. */
! 247: sili_pread_fis(sp, err_slot, &ccb->ccb_xa.rfis);
! 248: break;
! 249:
! 250: case SILI_PREG_CE_SDBERROR:
! 251: /* No NCQ commands active? Treat as a normal error. */
! 252: sactive = sili_pread(sp, SILI_PREG_SACT);/* XXX Pmult */
! 253: if (sactive == 0)
! 254: break;
! 255:
! 256: /* Extract real NCQ error slot & RFIS from log page. */
! 257: if (!sili_read_ncq_error(sp, &err_slot)) {
! 258: /* got real err_slot */
! 259: ccb = &sp->sp_ccbs[err_slot];
! 260: break;
! 261: }
! 262:
! 263: /* failed to get error or not NCQ */
! 264:
! 265: /* FALLTHROUGH */
! 266: default:
! 267: /* All other error types are fatal. */
! 268: printf("%s: fatal error (%d), aborting active slots "
! 269: "(%08x) and resetting device.\n", PORTNAME(sp),
! 270: err_code, pss_saved);
! 271: while (pss_saved) {
! 272: slot = ffs(pss_saved) - 1;
! 273: pss_saved &= ~(1 << slot);
! 274:
! 275: ccb = &sp->sp_ccbs[slot];
! 276: KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
! 277: ccb->ccb_xa.state = ATA_S_ERROR;
! 278: }
! 279: need_restart = SILI_PREG_PCS_DEVRESET;
! 280: goto fatal;
! 281: }
! 282:
! 283: DPRINTF(SILI_D_VERBOSE, "%s: %serror, code %d, slot %d, "
! 284: "active %08x\n", PORTNAME(sp), sactive ? "NCQ " : "",
! 285: err_code, err_slot, sp->sp_active);
! 286:
! 287: /* Clear the failed commmand in saved PSS so cmd_done runs. */
! 288: pss_saved &= ~(1 << err_slot);
! 289:
! 290: KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
! 291: ccb->ccb_xa.state = ATA_S_ERROR;
! 292:
! 293: need_restart = SILI_PREG_PCS_PORTINIT;
! 294: }
! 295: fatal:
! 296:
! 297: /* Process command timeout request only if command is still active. */
! 298: if (timeout_slot >= 0 && (pss_saved & (1 << timeout_slot))) {
! 299: DPRINTF(SILI_D_VERBOSE, "%s: timing out slot %d, active %08x\n",
! 300: PORTNAME(sp), timeout_slot, sp->sp_active);
! 301:
! 302: /* Clear the failed commmand in saved PSS so cmd_done runs. */
! 303: pss_saved &= ~(1 << timeout_slot);
! 304:
! 305: ccb = &sp->sp_ccbs[timeout_slot];
! 306: KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
! 307: ccb->ccb_xa.state = ATA_S_TIMEOUT;
! 308:
! 309: /* Reset device to abort all commands (including this one). */
! 310: need_restart = SILI_PREG_PCS_DEVRESET;
! 311: }
! 312:
! 313: /* Command slot is complete if its bit in PSS is 0 but 1 in active. */
! 314: pss_masked = ~pss_saved & sp->sp_active;
! 315: while (pss_masked) {
! 316: slot = ffs(pss_masked) - 1;
! 317: ccb = &sp->sp_ccbs[slot];
! 318: pss_masked &= ~(1 << slot);
! 319:
! 320: DPRINTF(SILI_D_INTR, "%s: slot %d is complete%s\n",
! 321: PORTNAME(sp), slot, ccb->ccb_xa.state == ATA_S_ERROR ?
! 322: " (error)" : (ccb->ccb_xa.state == ATA_S_TIMEOUT ?
! 323: " (timeout)" : ""));
! 324:
! 325: sili_ata_cmd_done(ccb, need_restart);
! 326:
! 327: processed |= 1 << slot;
! 328: }
! 329:
! 330: if (need_restart) {
! 331: /* Re-enable transfers on port. */
! 332: sili_pwrite(sp, SILI_PREG_PCS, need_restart);
! 333: if (!sili_pwait_eq(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRDY,
! 334: SILI_PREG_PCS_PORTRDY, 1000)) {
! 335: printf("%s: couldn't restart port after error\n",
! 336: PORTNAME(sp));
! 337: }
! 338:
! 339: /* Restart CCBs in the order they were originally queued. */
! 340: pss_masked = pss_saved;
! 341: TAILQ_FOREACH(ccb, &sp->sp_active_ccbs, ccb_entry) {
! 342: DPRINTF(SILI_D_VERBOSE, "%s: restarting slot %d "
! 343: "after error, state %02x\n", PORTNAME(sp),
! 344: ccb->ccb_xa.tag, ccb->ccb_xa.state);
! 345: if (!(pss_masked & (1 << ccb->ccb_xa.tag))) {
! 346: panic("sili_intr: slot %d not active in "
! 347: "pss_masked: %08x, state %02x",
! 348: ccb->ccb_xa.tag, pss_masked,
! 349: ccb->ccb_xa.state);
! 350: }
! 351: pss_masked &= ~(1 << ccb->ccb_xa.tag);
! 352:
! 353: KASSERT(ccb->ccb_xa.state == ATA_S_ONCHIP);
! 354: sili_post_indirect(sp, ccb);
! 355: }
! 356: KASSERT(pss_masked == 0);
! 357:
! 358: /*
! 359: * Finally, run atascsi completion for any finished CCBs. If
! 360: * we had run these during cmd_done above, any ccbs that their
! 361: * completion generated would have been activated out of order.
! 362: */
! 363: while ((ccb = TAILQ_FIRST(&sp->sp_deferred_ccbs)) != NULL) {
! 364: TAILQ_REMOVE(&sp->sp_deferred_ccbs, ccb, ccb_entry);
! 365:
! 366: KASSERT(ccb->ccb_xa.state == ATA_S_COMPLETE ||
! 367: ccb->ccb_xa.state == ATA_S_ERROR ||
! 368: ccb->ccb_xa.state == ATA_S_TIMEOUT);
! 369: ccb->ccb_xa.complete(&ccb->ccb_xa);
! 370: }
! 371: }
! 372:
! 373: return (processed);
! 374: }
! 375:
! 376: int
! 377: sili_intr(void *arg)
! 378: {
! 379: struct sili_softc *sc = arg;
! 380: u_int32_t is;
! 381: int port;
! 382:
! 383: is = sili_read(sc, SILI_REG_GIS);
! 384: if (is == 0)
! 385: return (0);
! 386: sili_write(sc, SILI_REG_GIS, is);
! 387: DPRINTF(SILI_D_INTR, "sili_intr, GIS: %08x\n", is);
! 388:
! 389: while (is & SILI_REG_GIS_PIS_MASK) {
! 390: port = ffs(is) - 1;
! 391: sili_port_intr(&sc->sc_ports[port], -1);
! 392: is &= ~(1 << port);
! 393: }
! 394:
! 395: return (1);
! 396: }
! 397:
! 398: int
! 399: sili_ports_alloc(struct sili_softc *sc)
! 400: {
! 401: struct sili_port *sp;
! 402: int i;
! 403:
! 404: sc->sc_ports = malloc(sizeof(struct sili_port) * sc->sc_nports,
! 405: M_DEVBUF, M_WAITOK);
! 406: bzero(sc->sc_ports, sizeof(struct sili_port) * sc->sc_nports);
! 407:
! 408: for (i = 0; i < sc->sc_nports; i++) {
! 409: sp = &sc->sc_ports[i];
! 410:
! 411: sp->sp_sc = sc;
! 412: #ifdef SILI_DEBUG
! 413: snprintf(sp->sp_name, sizeof(sp->sp_name), "%s.%d",
! 414: DEVNAME(sc), i);
! 415: #endif
! 416: if (bus_space_subregion(sc->sc_iot_port, sc->sc_ioh_port,
! 417: SILI_PORT_OFFSET(i), SILI_PORT_SIZE, &sp->sp_ioh) != 0) {
! 418: printf("%s: unable to create register window "
! 419: "for port %d\n", DEVNAME(sc), i);
! 420: goto freeports;
! 421: }
! 422: }
! 423:
! 424: return (0);
! 425:
! 426: freeports:
! 427: /* bus_space(9) says subregions dont have to be freed */
! 428: free(sp, M_DEVBUF);
! 429: sc->sc_ports = NULL;
! 430: return (1);
! 431: }
! 432:
! 433: void
! 434: sili_ports_free(struct sili_softc *sc)
! 435: {
! 436: struct sili_port *sp;
! 437: int i;
! 438:
! 439: for (i = 0; i < sc->sc_nports; i++) {
! 440: sp = &sc->sc_ports[i];
! 441:
! 442: if (sp->sp_ccbs != NULL)
! 443: sili_ccb_free(sp);
! 444: }
! 445:
! 446: /* bus_space(9) says subregions dont have to be freed */
! 447: free(sc->sc_ports, M_DEVBUF);
! 448: sc->sc_ports = NULL;
! 449: }
! 450:
! 451: int
! 452: sili_ccb_alloc(struct sili_port *sp)
! 453: {
! 454: struct sili_softc *sc = sp->sp_sc;
! 455: struct sili_ccb *ccb;
! 456: struct sili_prb *prb;
! 457: int i;
! 458:
! 459: TAILQ_INIT(&sp->sp_free_ccbs);
! 460: TAILQ_INIT(&sp->sp_active_ccbs);
! 461: TAILQ_INIT(&sp->sp_deferred_ccbs);
! 462:
! 463: sp->sp_ccbs = malloc(sizeof(struct sili_ccb) * SILI_MAX_CMDS,
! 464: M_DEVBUF, M_WAITOK);
! 465: sp->sp_cmds = sili_dmamem_alloc(sc, SILI_CMD_LEN * SILI_MAX_CMDS,
! 466: SILI_PRB_ALIGN);
! 467: if (sp->sp_cmds == NULL)
! 468: goto free_ccbs;
! 469: sp->sp_scratch = sili_dmamem_alloc(sc, SILI_SCRATCH_LEN, PAGE_SIZE);
! 470: if (sp->sp_scratch == NULL)
! 471: goto free_cmds;
! 472:
! 473: bzero(sp->sp_ccbs, sizeof(struct sili_ccb) * SILI_MAX_CMDS);
! 474:
! 475: for (i = 0; i < SILI_MAX_CMDS; i++) {
! 476: ccb = &sp->sp_ccbs[i];
! 477: ccb->ccb_port = sp;
! 478: ccb->ccb_cmd = SILI_DMA_KVA(sp->sp_cmds) + i * SILI_CMD_LEN;
! 479: ccb->ccb_cmd_dva = SILI_DMA_DVA(sp->sp_cmds) + i * SILI_CMD_LEN;
! 480: if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, SILI_DMA_SEGS,
! 481: MAXPHYS, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW,
! 482: &ccb->ccb_dmamap) != 0)
! 483: goto free_scratch;
! 484:
! 485: prb = ccb->ccb_cmd;
! 486: ccb->ccb_xa.fis = (struct ata_fis_h2d *)&prb->fis;
! 487: ccb->ccb_xa.packetcmd = ((struct sili_prb_packet *)prb)->cdb;
! 488: ccb->ccb_xa.tag = i;
! 489: ccb->ccb_xa.ata_put_xfer = sili_ata_put_xfer;
! 490: ccb->ccb_xa.state = ATA_S_COMPLETE;
! 491:
! 492: sili_put_ccb(ccb);
! 493: }
! 494:
! 495: return (0);
! 496:
! 497: free_scratch:
! 498: sili_dmamem_free(sc, sp->sp_scratch);
! 499: free_cmds:
! 500: sili_dmamem_free(sc, sp->sp_cmds);
! 501: free_ccbs:
! 502: sili_ccb_free(sp);
! 503: return (1);
! 504: }
! 505:
! 506: void
! 507: sili_ccb_free(struct sili_port *sp)
! 508: {
! 509: struct sili_softc *sc = sp->sp_sc;
! 510: struct sili_ccb *ccb;
! 511:
! 512: while ((ccb = sili_get_ccb(sp)) != NULL)
! 513: bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
! 514:
! 515: free(sp->sp_ccbs, M_DEVBUF);
! 516: sp->sp_ccbs = NULL;
! 517: }
! 518:
! 519: struct sili_ccb *
! 520: sili_get_ccb(struct sili_port *sp)
! 521: {
! 522: struct sili_ccb *ccb;
! 523:
! 524: ccb = TAILQ_FIRST(&sp->sp_free_ccbs);
! 525: if (ccb != NULL) {
! 526: KASSERT(ccb->ccb_xa.state == ATA_S_PUT);
! 527: TAILQ_REMOVE(&sp->sp_free_ccbs, ccb, ccb_entry);
! 528: ccb->ccb_xa.state = ATA_S_SETUP;
! 529: }
! 530:
! 531: return (ccb);
! 532: }
! 533:
! 534: void
! 535: sili_put_ccb(struct sili_ccb *ccb)
! 536: {
! 537: struct sili_port *sp = ccb->ccb_port;
! 538:
! 539: #ifdef DIAGNOSTIC
! 540: if (ccb->ccb_xa.state != ATA_S_COMPLETE &&
! 541: ccb->ccb_xa.state != ATA_S_TIMEOUT &&
! 542: ccb->ccb_xa.state != ATA_S_ERROR) {
! 543: printf("%s: invalid ata_xfer state %02x in sili_put_ccb, "
! 544: "slot %d\n", PORTNAME(sp), ccb->ccb_xa.state,
! 545: ccb->ccb_xa.tag);
! 546: }
! 547: #endif
! 548:
! 549: ccb->ccb_xa.state = ATA_S_PUT;
! 550: TAILQ_INSERT_TAIL(&sp->sp_free_ccbs, ccb, ccb_entry);
! 551: }
! 552:
! 553: struct sili_dmamem *
! 554: sili_dmamem_alloc(struct sili_softc *sc, bus_size_t size, bus_size_t align)
! 555: {
! 556: struct sili_dmamem *sdm;
! 557: int nsegs;
! 558:
! 559: sdm = malloc(sizeof(struct sili_dmamem), M_DEVBUF, M_WAITOK);
! 560: bzero(sdm, sizeof(struct sili_dmamem));
! 561: sdm->sdm_size = size;
! 562:
! 563: if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
! 564: BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &sdm->sdm_map) != 0)
! 565: goto sdmfree;
! 566:
! 567: if (bus_dmamem_alloc(sc->sc_dmat, size, align, 0, &sdm->sdm_seg,
! 568: 1, &nsegs, BUS_DMA_NOWAIT) != 0)
! 569: goto destroy;
! 570:
! 571: if (bus_dmamem_map(sc->sc_dmat, &sdm->sdm_seg, nsegs, size,
! 572: &sdm->sdm_kva, BUS_DMA_NOWAIT) != 0)
! 573: goto free;
! 574:
! 575: if (bus_dmamap_load(sc->sc_dmat, sdm->sdm_map, sdm->sdm_kva, size,
! 576: NULL, BUS_DMA_NOWAIT) != 0)
! 577: goto unmap;
! 578:
! 579: bzero(sdm->sdm_kva, size);
! 580:
! 581: return (sdm);
! 582:
! 583: unmap:
! 584: bus_dmamem_unmap(sc->sc_dmat, sdm->sdm_kva, size);
! 585: free:
! 586: bus_dmamem_free(sc->sc_dmat, &sdm->sdm_seg, 1);
! 587: destroy:
! 588: bus_dmamap_destroy(sc->sc_dmat, sdm->sdm_map);
! 589: sdmfree:
! 590: free(sdm, M_DEVBUF);
! 591:
! 592: return (NULL);
! 593: }
! 594:
! 595: void
! 596: sili_dmamem_free(struct sili_softc *sc, struct sili_dmamem *sdm)
! 597: {
! 598: bus_dmamap_unload(sc->sc_dmat, sdm->sdm_map);
! 599: bus_dmamem_unmap(sc->sc_dmat, sdm->sdm_kva, sdm->sdm_size);
! 600: bus_dmamem_free(sc->sc_dmat, &sdm->sdm_seg, 1);
! 601: bus_dmamap_destroy(sc->sc_dmat, sdm->sdm_map);
! 602: free(sdm, M_DEVBUF);
! 603: }
! 604:
! 605: u_int32_t
! 606: sili_read(struct sili_softc *sc, bus_size_t r)
! 607: {
! 608: u_int32_t rv;
! 609:
! 610: bus_space_barrier(sc->sc_iot_global, sc->sc_ioh_global, r, 4,
! 611: BUS_SPACE_BARRIER_READ);
! 612: rv = bus_space_read_4(sc->sc_iot_global, sc->sc_ioh_global, r);
! 613:
! 614: return (rv);
! 615: }
! 616:
! 617: void
! 618: sili_write(struct sili_softc *sc, bus_size_t r, u_int32_t v)
! 619: {
! 620: bus_space_write_4(sc->sc_iot_global, sc->sc_ioh_global, r, v);
! 621: bus_space_barrier(sc->sc_iot_global, sc->sc_ioh_global, r, 4,
! 622: BUS_SPACE_BARRIER_WRITE);
! 623: }
! 624:
! 625: u_int32_t
! 626: sili_pread(struct sili_port *sp, bus_size_t r)
! 627: {
! 628: u_int32_t rv;
! 629:
! 630: bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, 4,
! 631: BUS_SPACE_BARRIER_READ);
! 632: rv = bus_space_read_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r);
! 633:
! 634: return (rv);
! 635: }
! 636:
! 637: void
! 638: sili_pwrite(struct sili_port *sp, bus_size_t r, u_int32_t v)
! 639: {
! 640: bus_space_write_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, v);
! 641: bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, 4,
! 642: BUS_SPACE_BARRIER_WRITE);
! 643: }
! 644:
! 645: int
! 646: sili_pwait_eq(struct sili_port *sp, bus_size_t r, u_int32_t mask,
! 647: u_int32_t value, int timeout)
! 648: {
! 649: while ((sili_pread(sp, r) & mask) != value) {
! 650: if (timeout == 0)
! 651: return (0);
! 652:
! 653: delay(1000);
! 654: timeout--;
! 655: }
! 656:
! 657: return (1);
! 658: }
! 659:
! 660: int
! 661: sili_pwait_ne(struct sili_port *sp, bus_size_t r, u_int32_t mask,
! 662: u_int32_t value, int timeout)
! 663: {
! 664: while ((sili_pread(sp, r) & mask) == value) {
! 665: if (timeout == 0)
! 666: return (0);
! 667:
! 668: delay(1000);
! 669: timeout--;
! 670: }
! 671:
! 672: return (1);
! 673: }
! 674:
! 675: void
! 676: sili_post_direct(struct sili_port *sp, u_int slot, void *buf, size_t buflen)
! 677: {
! 678: bus_size_t r = SILI_PREG_SLOT(slot);
! 679:
! 680: #ifdef DIAGNOSTIC
! 681: if (buflen != 64 && buflen != 128)
! 682: panic("sili_pcopy: buflen of %d is not 64 or 128", buflen);
! 683: #endif
! 684:
! 685: bus_space_write_raw_region_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
! 686: buf, buflen);
! 687: bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r, buflen,
! 688: BUS_SPACE_BARRIER_WRITE);
! 689:
! 690: sili_pwrite(sp, SILI_PREG_FIFO, slot);
! 691: }
! 692:
! 693: void
! 694: sili_pread_fis(struct sili_port *sp, u_int slot, struct ata_fis_d2h *fis)
! 695: {
! 696: bus_size_t r = SILI_PREG_SLOT(slot) + 8;
! 697:
! 698: bus_space_barrier(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
! 699: sizeof(struct ata_fis_d2h), BUS_SPACE_BARRIER_READ);
! 700: bus_space_read_raw_region_4(sp->sp_sc->sc_iot_port, sp->sp_ioh, r,
! 701: fis, sizeof(struct ata_fis_d2h));
! 702: }
! 703:
! 704: void
! 705: sili_post_indirect(struct sili_port *sp, struct sili_ccb *ccb)
! 706: {
! 707: sili_pwrite(sp, SILI_PREG_CAR_LO(ccb->ccb_xa.tag),
! 708: (u_int32_t)ccb->ccb_cmd_dva);
! 709: sili_pwrite(sp, SILI_PREG_CAR_HI(ccb->ccb_xa.tag),
! 710: (u_int32_t)(ccb->ccb_cmd_dva >> 32));
! 711: }
! 712:
! 713: u_int32_t
! 714: sili_signature(struct sili_port *sp, u_int slot)
! 715: {
! 716: u_int32_t sig_hi, sig_lo;
! 717:
! 718: sig_hi = sili_pread(sp, SILI_PREG_SIG_HI(slot));
! 719: sig_hi <<= SILI_PREG_SIG_HI_SHIFT;
! 720: sig_lo = sili_pread(sp, SILI_PREG_SIG_LO(slot));
! 721: sig_lo &= SILI_PREG_SIG_LO_MASK;
! 722:
! 723: return (sig_hi | sig_lo);
! 724: }
! 725:
! 726: int
! 727: sili_ata_probe(void *xsc, int port)
! 728: {
! 729: struct sili_softc *sc = xsc;
! 730: struct sili_port *sp = &sc->sc_ports[port];
! 731: struct sili_prb_softreset sreset;
! 732: u_int32_t signature;
! 733: int port_type;
! 734:
! 735: sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_PORTRESET);
! 736: sili_pwrite(sp, SILI_PREG_PCC, SILI_PREG_PCC_A32B);
! 737:
! 738: if (!sili_pwait_eq(sp, SILI_PREG_SSTS, SATA_SStatus_DET,
! 739: SATA_SStatus_DET_DEV, 1000))
! 740: return (ATA_PORT_T_NONE);
! 741:
! 742: DPRINTF(SILI_D_VERBOSE, "%s: SSTS 0x%08x\n", PORTNAME(sp),
! 743: sili_pread(sp, SILI_PREG_SSTS));
! 744:
! 745: bzero(&sreset, sizeof(sreset));
! 746: sreset.control = htole16(SILI_PRB_SOFT_RESET | SILI_PRB_INTERRUPT_MASK);
! 747: /* XXX sreset fis pmp field */
! 748:
! 749: /* we use slot 0 */
! 750: sili_post_direct(sp, 0, &sreset, sizeof(sreset));
! 751: if (!sili_pwait_eq(sp, SILI_PREG_PSS, (1 << 0), 0, 1000)) {
! 752: DPRINTF(SILI_D_VERBOSE, "%s: timed out while waiting for soft "
! 753: "reset\n", PORTNAME(sp));
! 754: return (ATA_PORT_T_NONE);
! 755: }
! 756:
! 757: /* Read device signature from command slot. */
! 758: signature = sili_signature(sp, 0);
! 759:
! 760: DPRINTF(SILI_D_VERBOSE, "%s: signature 0x%08x\n", PORTNAME(sp),
! 761: signature);
! 762:
! 763: switch (signature) {
! 764: case SATA_SIGNATURE_DISK:
! 765: port_type = ATA_PORT_T_DISK;
! 766: break;
! 767: case SATA_SIGNATURE_ATAPI:
! 768: port_type = ATA_PORT_T_ATAPI;
! 769: break;
! 770: case SATA_SIGNATURE_PORT_MULTIPLIER:
! 771: default:
! 772: return (ATA_PORT_T_NONE);
! 773: }
! 774:
! 775: /* allocate port resources */
! 776: if (sili_ccb_alloc(sp) != 0)
! 777: return (ATA_PORT_T_NONE);
! 778:
! 779: /* enable port interrupts */
! 780: sili_write(sc, SILI_REG_GC, sili_read(sc, SILI_REG_GC) | 1 << port);
! 781: sili_pwrite(sp, SILI_PREG_IES, SILI_PREG_IE_CMDERR |
! 782: SILI_PREG_IE_CMDCOMP);
! 783:
! 784: return (port_type);
! 785: }
! 786:
! 787: int
! 788: sili_ata_cmd(struct ata_xfer *xa)
! 789: {
! 790: struct sili_ccb *ccb = (struct sili_ccb *)xa;
! 791: struct sili_port *sp = ccb->ccb_port;
! 792: struct sili_softc *sc = sp->sp_sc;
! 793: struct sili_prb_ata *ata;
! 794: struct sili_prb_packet *atapi;
! 795: struct sili_sge *sgl;
! 796: int sgllen;
! 797: int s;
! 798:
! 799: KASSERT(xa->state == ATA_S_SETUP);
! 800:
! 801: if (xa->flags & ATA_F_PACKET) {
! 802: atapi = ccb->ccb_cmd;
! 803:
! 804: if (xa->flags & ATA_F_WRITE)
! 805: atapi->control = htole16(SILI_PRB_PACKET_WRITE);
! 806: else
! 807: atapi->control = htole16(SILI_PRB_PACKET_READ);
! 808:
! 809: sgl = atapi->sgl;
! 810: sgllen = sizeofa(atapi->sgl);
! 811: } else {
! 812: ata = ccb->ccb_cmd;
! 813:
! 814: ata->control = 0;
! 815:
! 816: sgl = ata->sgl;
! 817: sgllen = sizeofa(ata->sgl);
! 818: }
! 819:
! 820: if (sili_load(ccb, sgl, sgllen) != 0)
! 821: goto failcmd;
! 822:
! 823: bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_cmds),
! 824: xa->tag * SILI_CMD_LEN, SILI_CMD_LEN, BUS_DMASYNC_PREWRITE);
! 825:
! 826: timeout_set(&xa->stimeout, sili_ata_cmd_timeout, ccb);
! 827:
! 828: xa->state = ATA_S_PENDING;
! 829:
! 830: if (xa->flags & ATA_F_POLL) {
! 831: sili_poll(ccb, xa->timeout, sili_ata_cmd_timeout);
! 832: return (ATA_COMPLETE);
! 833: }
! 834:
! 835: timeout_add(&xa->stimeout, (xa->timeout * hz) / 1000);
! 836:
! 837: s = splbio();
! 838: sili_start(sp, ccb);
! 839: splx(s);
! 840: return (ATA_QUEUED);
! 841:
! 842: failcmd:
! 843: s = splbio();
! 844: xa->state = ATA_S_ERROR;
! 845: xa->complete(xa);
! 846: splx(s);
! 847: return (ATA_ERROR);
! 848: }
! 849:
! 850: void
! 851: sili_ata_cmd_done(struct sili_ccb *ccb, int defer_completion)
! 852: {
! 853: struct sili_port *sp = ccb->ccb_port;
! 854: struct sili_softc *sc = sp->sp_sc;
! 855: struct ata_xfer *xa = &ccb->ccb_xa;
! 856:
! 857: splassert(IPL_BIO);
! 858:
! 859: timeout_del(&xa->stimeout);
! 860:
! 861: bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_cmds),
! 862: xa->tag * SILI_CMD_LEN, SILI_CMD_LEN, BUS_DMASYNC_POSTWRITE);
! 863:
! 864: sili_unload(ccb);
! 865:
! 866: TAILQ_REMOVE(&sp->sp_active_ccbs, ccb, ccb_entry);
! 867: sp->sp_active &= ~(1 << xa->tag);
! 868:
! 869: if (xa->state == ATA_S_ONCHIP)
! 870: xa->state = ATA_S_COMPLETE;
! 871: #ifdef DIAGNOSTIC
! 872: else if (xa->state != ATA_S_ERROR && xa->state != ATA_S_TIMEOUT)
! 873: printf("%s: invalid ata_xfer state %02x in sili_ata_cmd_done, "
! 874: "slot %d\n", PORTNAME(sp), xa->state, xa->tag);
! 875: #endif
! 876: if (defer_completion)
! 877: TAILQ_INSERT_TAIL(&sp->sp_deferred_ccbs, ccb, ccb_entry);
! 878: else if (xa->state == ATA_S_COMPLETE)
! 879: xa->complete(xa);
! 880: #ifdef DIAGNOSTIC
! 881: else
! 882: printf("%s: completion not deferred, but xa->state is %02x?\n",
! 883: PORTNAME(sp), xa->state);
! 884: #endif
! 885: }
! 886:
! 887: void
! 888: sili_ata_cmd_timeout(void *xccb)
! 889: {
! 890: struct sili_ccb *ccb = xccb;
! 891: struct sili_port *sp = ccb->ccb_port;
! 892: int s;
! 893:
! 894: s = splbio();
! 895: sili_port_intr(sp, ccb->ccb_xa.tag);
! 896: splx(s);
! 897: }
! 898:
! 899: int
! 900: sili_load(struct sili_ccb *ccb, struct sili_sge *sgl, int sgllen)
! 901: {
! 902: struct sili_port *sp = ccb->ccb_port;
! 903: struct sili_softc *sc = sp->sp_sc;
! 904: struct ata_xfer *xa = &ccb->ccb_xa;
! 905: struct sili_sge *nsge = sgl, *ce = NULL;
! 906: bus_dmamap_t dmap = ccb->ccb_dmamap;
! 907: u_int64_t addr;
! 908: int error;
! 909: int i;
! 910:
! 911: if (xa->datalen == 0)
! 912: return (0);
! 913:
! 914: error = bus_dmamap_load(sc->sc_dmat, dmap, xa->data, xa->datalen, NULL,
! 915: (xa->flags & ATA_F_NOWAIT) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
! 916: if (error != 0) {
! 917: printf("%s: error %d loading dmamap\n", PORTNAME(sp), error);
! 918: return (1);
! 919: }
! 920:
! 921: if (dmap->dm_nsegs > sgllen)
! 922: ce = &sgl[sgllen - 1];
! 923:
! 924: for (i = 0; i < dmap->dm_nsegs; i++) {
! 925: if (nsge == ce) {
! 926: nsge++;
! 927:
! 928: addr = ccb->ccb_cmd_dva;
! 929: addr += ((u_int8_t *)nsge - (u_int8_t *)ccb->ccb_cmd);
! 930:
! 931: ce->addr_lo = htole32((u_int32_t)addr);
! 932: ce->addr_hi = htole32((u_int32_t)(addr >> 32));
! 933: ce->flags = htole32(SILI_SGE_LNK);
! 934:
! 935: if ((dmap->dm_nsegs - i) > SILI_SGT_SGLLEN)
! 936: ce += SILI_SGT_SGLLEN;
! 937: else
! 938: ce = NULL;
! 939: }
! 940:
! 941: sgl = nsge;
! 942:
! 943: addr = dmap->dm_segs[i].ds_addr;
! 944: sgl->addr_lo = htole32((u_int32_t)addr);
! 945: sgl->addr_hi = htole32((u_int32_t)(addr >> 32));
! 946: sgl->data_count = htole32(dmap->dm_segs[i].ds_len);
! 947: sgl->flags = 0;
! 948:
! 949: nsge++;
! 950: }
! 951: sgl->flags |= htole32(SILI_SGE_TRM);
! 952:
! 953: bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
! 954: (xa->flags & ATA_F_READ) ? BUS_DMASYNC_PREREAD :
! 955: BUS_DMASYNC_PREWRITE);
! 956:
! 957: return (0);
! 958: }
! 959:
! 960: void
! 961: sili_unload(struct sili_ccb *ccb)
! 962: {
! 963: struct sili_port *sp = ccb->ccb_port;
! 964: struct sili_softc *sc = sp->sp_sc;
! 965: struct ata_xfer *xa = &ccb->ccb_xa;
! 966: bus_dmamap_t dmap = ccb->ccb_dmamap;
! 967:
! 968: if (xa->datalen == 0)
! 969: return;
! 970:
! 971: bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
! 972: (xa->flags & ATA_F_READ) ? BUS_DMASYNC_POSTREAD :
! 973: BUS_DMASYNC_POSTWRITE);
! 974: bus_dmamap_unload(sc->sc_dmat, dmap);
! 975:
! 976: if (xa->flags & ATA_F_READ)
! 977: xa->resid = xa->datalen - sili_pread(sp,
! 978: SILI_PREG_RX_COUNT(xa->tag));
! 979: else
! 980: xa->resid = 0;
! 981: }
! 982:
! 983: int
! 984: sili_poll(struct sili_ccb *ccb, int timeout, void (*timeout_fn)(void *))
! 985: {
! 986: struct sili_port *sp = ccb->ccb_port;
! 987: int s;
! 988:
! 989: s = splbio();
! 990: sili_start(sp, ccb);
! 991: do {
! 992: if (sili_port_intr(sp, -1) & (1 << ccb->ccb_xa.tag)) {
! 993: splx(s);
! 994: return (0);
! 995: }
! 996:
! 997: delay(1000);
! 998: } while (--timeout > 0);
! 999:
! 1000: /* Run timeout while at splbio, otherwise sili_intr could interfere. */
! 1001: if (timeout_fn != NULL)
! 1002: timeout_fn(ccb);
! 1003:
! 1004: splx(s);
! 1005:
! 1006: return (1);
! 1007: }
! 1008:
! 1009: void
! 1010: sili_start(struct sili_port *sp, struct sili_ccb *ccb)
! 1011: {
! 1012: int slot = ccb->ccb_xa.tag;
! 1013:
! 1014: splassert(IPL_BIO);
! 1015: KASSERT(ccb->ccb_xa.state == ATA_S_PENDING);
! 1016:
! 1017: TAILQ_INSERT_TAIL(&sp->sp_active_ccbs, ccb, ccb_entry);
! 1018: sp->sp_active |= 1 << slot;
! 1019: ccb->ccb_xa.state = ATA_S_ONCHIP;
! 1020:
! 1021: sili_post_indirect(sp, ccb);
! 1022: }
! 1023:
! 1024: int
! 1025: sili_read_ncq_error(struct sili_port *sp, int *err_slotp)
! 1026: {
! 1027: struct sili_softc *sc = sp->sp_sc;
! 1028: struct sili_prb_ata read_10h;
! 1029: u_int64_t addr;
! 1030: struct ata_fis_h2d *fis;
! 1031: struct ata_log_page_10h *log;
! 1032: struct sili_ccb *ccb;
! 1033: int rc;
! 1034:
! 1035: sili_pwrite(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTINIT);
! 1036: if (!sili_pwait_eq(sp, SILI_PREG_PCS, SILI_PREG_PCS_PORTRDY,
! 1037: SILI_PREG_PCS_PORTRDY, 1000)) {
! 1038: printf("%s: couldn't ready port during log page read\n",
! 1039: PORTNAME(sp));
! 1040: return (1);
! 1041: }
! 1042:
! 1043: /* READ LOG EXT 10h into scratch space */
! 1044: bzero(&read_10h, sizeof(read_10h));
! 1045: read_10h.control = htole16(SILI_PRB_INTERRUPT_MASK);
! 1046:
! 1047: addr = SILI_DMA_DVA(sp->sp_scratch);
! 1048: read_10h.sgl[0].addr_lo = htole32((u_int32_t)addr);
! 1049: read_10h.sgl[0].addr_hi = htole32((u_int32_t)(addr >> 32));
! 1050: read_10h.sgl[0].data_count = htole32(512);
! 1051: read_10h.sgl[0].flags = htole32(SILI_SGE_TRM);
! 1052:
! 1053: fis = (struct ata_fis_h2d *)read_10h.fis;
! 1054: fis->type = ATA_FIS_TYPE_H2D;
! 1055: fis->flags = ATA_H2D_FLAGS_CMD; /* XXX fis pmp field */
! 1056: fis->command = ATA_C_READ_LOG_EXT;
! 1057: fis->lba_low = 0x10; /* queued error log page (10h) */
! 1058: fis->sector_count = 1; /* number of sectors (1) */
! 1059: fis->sector_count_exp = 0;
! 1060: fis->lba_mid = 0; /* starting offset */
! 1061: fis->lba_mid_exp = 0;
! 1062: fis->device = 0;
! 1063:
! 1064: bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_scratch), 0,
! 1065: 512, BUS_DMASYNC_PREREAD);
! 1066:
! 1067: /* issue read and poll for completion */
! 1068: sili_post_direct(sp, 0, &read_10h, sizeof(read_10h));
! 1069: rc = sili_pwait_eq(sp, SILI_PREG_PSS, (1 << 0), 0, 1000);
! 1070:
! 1071: bus_dmamap_sync(sc->sc_dmat, SILI_DMA_MAP(sp->sp_scratch), 0,
! 1072: 512, BUS_DMASYNC_POSTREAD);
! 1073:
! 1074: if (!rc) {
! 1075: DPRINTF(SILI_D_VERBOSE, "%s: timed out while waiting for log "
! 1076: "page read\n", PORTNAME(sp));
! 1077: return (1);
! 1078: }
! 1079:
! 1080: /* Extract failed register set and tags from the scratch space. */
! 1081: log = (struct ata_log_page_10h *)SILI_DMA_KVA(sp->sp_scratch);
! 1082: if (ISSET(log->err_regs.type, ATA_LOG_10H_TYPE_NOTQUEUED)) {
! 1083: /* Not queued bit was set - wasn't an NCQ error? */
! 1084: printf("%s: read NCQ error page, but not an NCQ error?\n",
! 1085: PORTNAME(sp));
! 1086: return (1);
! 1087: }
! 1088:
! 1089: /* Copy back the log record as a D2H register FIS. */
! 1090: *err_slotp = log->err_regs.type & ATA_LOG_10H_TYPE_TAG_MASK;
! 1091:
! 1092: ccb = &sp->sp_ccbs[*err_slotp];
! 1093: memcpy(&ccb->ccb_xa.rfis, &log->err_regs, sizeof(struct ata_fis_d2h));
! 1094: ccb->ccb_xa.rfis.type = ATA_FIS_TYPE_D2H;
! 1095: ccb->ccb_xa.rfis.flags = 0;
! 1096:
! 1097: return (0);
! 1098: }
! 1099:
! 1100: struct ata_xfer *
! 1101: sili_ata_get_xfer(void *xsc, int port)
! 1102: {
! 1103: struct sili_softc *sc = xsc;
! 1104: struct sili_port *sp = &sc->sc_ports[port];
! 1105: struct sili_ccb *ccb;
! 1106:
! 1107: ccb = sili_get_ccb(sp);
! 1108: if (ccb == NULL) {
! 1109: printf("sili_ata_get_xfer: NULL ccb\n");
! 1110: return (NULL);
! 1111: }
! 1112:
! 1113: bzero(ccb->ccb_cmd, SILI_CMD_LEN);
! 1114:
! 1115: return ((struct ata_xfer *)ccb);
! 1116: }
! 1117:
! 1118: void
! 1119: sili_ata_put_xfer(struct ata_xfer *xa)
! 1120: {
! 1121: struct sili_ccb *ccb = (struct sili_ccb *)xa;
! 1122:
! 1123: sili_put_ccb(ccb);
! 1124: }
CVSweb