[BACK]Return to sili.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/sili.c, Revision 1.1.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