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

Annotation of sys/dev/ic/aic79xx_openbsd.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: aic79xx_openbsd.c,v 1.26 2006/11/28 23:59:45 dlg Exp $        */
                      2:
                      3: /*
                      4:  * Copyright (c) 2004 Milos Urbanek, Kenneth R. Westerback & Marco Peereboom
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  *
                     16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
                     17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     19:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
                     20:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     26:  * SUCH DAMAGE.
                     27:  *
                     28:  */
                     29:
                     30: /*
                     31:  * Bus independent OpenBSD shim for the aic79xx based Adaptec SCSI controllers
                     32:  *
                     33:  * Copyright (c) 1994-2002 Justin T. Gibbs.
                     34:  * Copyright (c) 2001-2002 Adaptec Inc.
                     35:  * All rights reserved.
                     36:  *
                     37:  * Redistribution and use in source and binary forms, with or without
                     38:  * modification, are permitted provided that the following conditions
                     39:  * are met:
                     40:  * 1. Redistributions of source code must retain the above copyright
                     41:  *    notice, this list of conditions, and the following disclaimer,
                     42:  *    without modification.
                     43:  * 2. The name of the author may not be used to endorse or promote products
                     44:  *    derived from this software without specific prior written permission.
                     45:  *
                     46:  * Alternatively, this software may be distributed under the terms of the
                     47:  * GNU Public License ("GPL").
                     48:  *
                     49:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     52:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
                     53:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     59:  * SUCH DAMAGE.
                     60:  *
                     61:  */
                     62:
                     63: #include <sys/cdefs.h>
                     64: /*
                     65: __FBSDID("$FreeBSD: src/sys/dev/aic7xxx/aic79xx_osm.c,v 1.16 2003/12/17 00:02:09 gibbs Exp $");
                     66: */
                     67:
                     68: #include <dev/ic/aic79xx_openbsd.h>
                     69: #include <dev/ic/aic79xx_inline.h>
                     70: #include <dev/ic/aic79xx.h>
                     71:
                     72: #ifndef AHD_TMODE_ENABLE
                     73: #define AHD_TMODE_ENABLE 0
                     74: #endif
                     75:
                     76: /* XXX milos add ahd_ioctl */
                     77: int    ahd_action(struct scsi_xfer *);
                     78: int    ahd_execute_scb(void *, bus_dma_segment_t *, int);
                     79: int    ahd_poll(struct ahd_softc *, int);
                     80: int    ahd_setup_data(struct ahd_softc *, struct scsi_xfer *,
                     81:                    struct scb *);
                     82:
                     83: void   ahd_adapter_req_set_xfer_mode(struct ahd_softc *, struct scb *);
                     84: void    ahd_minphys(struct buf *);
                     85:
                     86: struct cfdriver ahd_cd = {
                     87:        NULL, "ahd", DV_DULL
                     88: };
                     89:
                     90: static struct scsi_adapter ahd_switch =
                     91: {
                     92:        ahd_action,
                     93:        ahd_minphys,
                     94:        0,
                     95:        0,
                     96: };
                     97:
                     98: /* the below structure is so we have a default dev struct for our link struct */
                     99: static struct scsi_device ahd_dev =
                    100: {
                    101:        NULL, /* Use default error handler */
                    102:        NULL, /* have a queue, served by this */
                    103:        NULL, /* have no async handler */
                    104:        NULL, /* Use default 'done' routine */
                    105: };
                    106:
                    107: /*
                    108:  * Attach all the sub-devices we can find
                    109:  */
                    110: int
                    111: ahd_attach(struct ahd_softc *ahd)
                    112: {
                    113:        struct scsibus_attach_args saa;
                    114:        char   ahd_info[256];
                    115:        int     s;
                    116:
                    117:        ahd_controller_info(ahd, ahd_info, sizeof ahd_info);
                    118:        printf("%s\n", ahd_info);
                    119:        ahd_lock(ahd, &s);
                    120:
                    121:        /*
                    122:         * fill in the prototype scsi_links.
                    123:         */
                    124:        ahd->sc_channel.adapter_target = ahd->our_id;
                    125:        if (ahd->features & AHD_WIDE)
                    126:                ahd->sc_channel.adapter_buswidth = 16;
                    127:        ahd->sc_channel.adapter_softc = ahd;
                    128:        ahd->sc_channel.adapter = &ahd_switch;
                    129:        ahd->sc_channel.openings = 16;
                    130:        ahd->sc_channel.device = &ahd_dev;
                    131:
                    132:        if (bootverbose) {
                    133:                ahd_controller_info(ahd, ahd_info, sizeof ahd_info);
                    134:                printf("%s: %s\n", ahd->sc_dev.dv_xname, ahd_info);
                    135:        }
                    136:
                    137:        ahd_intr_enable(ahd, TRUE);
                    138:
                    139:        if (ahd->flags & AHD_RESET_BUS_A)
                    140:                ahd_reset_channel(ahd, 'A', TRUE);
                    141:
                    142:        bzero(&saa, sizeof(saa));
                    143:        saa.saa_sc_link = &ahd->sc_channel;
                    144:
                    145:        ahd->sc_child = config_found((void *)&ahd->sc_dev, &saa, scsiprint);
                    146:
                    147:        ahd_unlock(ahd, &s);
                    148:
                    149:        return (1);
                    150:
                    151: }
                    152:
                    153: /*
                    154:  * Catch an interrupt from the adapter
                    155:  */
                    156: int
                    157: ahd_platform_intr(void *arg)
                    158: {
                    159:        struct  ahd_softc *ahd;
                    160:
                    161:        /* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */
                    162:
                    163:        ahd = (struct ahd_softc *)arg;
                    164:        return ahd_intr(ahd);
                    165: }
                    166:
                    167: /*
                    168:  * We have an scb which has been processed by the
                    169:  * adaptor, now we look to see how the operation
                    170:  * went.
                    171:  */
                    172: void
                    173: ahd_done(struct ahd_softc *ahd, struct scb *scb)
                    174: {
                    175:        struct scsi_xfer *xs = scb->xs;
                    176:        int s;
                    177:
                    178:        /* XXX in ahc there is some bus_dmamap_sync(PREREAD|PREWRITE); */
                    179:
                    180:        LIST_REMOVE(scb, pending_links);
                    181:
                    182:        timeout_del(&xs->stimeout);
                    183:
                    184:        if (xs->datalen) {
                    185:                int op;
                    186:
                    187:                if ((xs->flags & SCSI_DATA_IN) != 0)
                    188:                        op = BUS_DMASYNC_POSTREAD;
                    189:                else
                    190:                        op = BUS_DMASYNC_POSTWRITE;
                    191:                bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
                    192:                    scb->dmamap->dm_mapsize, op);
                    193:                bus_dmamap_unload(ahd->parent_dmat, scb->dmamap);
                    194:        }
                    195:
                    196:        /* Translate the CAM status code to a SCSI error code. */
                    197:        switch (xs->error) {
                    198:        case CAM_SCSI_STATUS_ERROR:
                    199:        case CAM_REQ_INPROG:
                    200:        case CAM_REQ_CMP:
                    201:                switch (xs->status) {
                    202:                case SCSI_TASKSET_FULL:
                    203:                        /* SCSI Layer won't requeue, so we force infinite
                    204:                         * retries until queue space is available. XS_BUSY
                    205:                         * is dangerous because if the NOSLEEP flag is set
                    206:                         * it can cause the I/O to return EIO. XS_BUSY code
                    207:                         * falls through to XS_TIMEOUT anyway.
                    208:                         */
                    209:                        xs->error = XS_TIMEOUT;
                    210:                        xs->retries++;
                    211:                        break;
                    212:                case SCSI_BUSY:
                    213:                        xs->error = XS_BUSY;
                    214:                        break;
                    215:                case SCSI_CHECK:
                    216:                case SCSI_TERMINATED:
                    217:                        if ((scb->flags & SCB_SENSE) == 0) {
                    218:                                /* CHECK on CHECK? */
                    219:                                xs->error = XS_DRIVER_STUFFUP;
                    220:                        } else
                    221:                                xs->error = XS_NOERROR;
                    222:                        break;
                    223:                default:
                    224:                        xs->error = XS_NOERROR;
                    225:                        break;
                    226:                }
                    227:                break;
                    228:        case CAM_BUSY:
                    229:                xs->error = XS_BUSY;
                    230:                break;
                    231:        case CAM_CMD_TIMEOUT:
                    232:                xs->error = XS_TIMEOUT;
                    233:                break;
                    234:        case CAM_BDR_SENT:
                    235:        case CAM_SCSI_BUS_RESET:
                    236:                xs->error = XS_RESET;
                    237:                break;
                    238:        case CAM_REQUEUE_REQ:
                    239:                xs->error = XS_TIMEOUT;
                    240:                xs->retries++;
                    241:                break;
                    242:        case CAM_SEL_TIMEOUT:
                    243:                xs->error = XS_SELTIMEOUT;
                    244:                break;
                    245:        default:
                    246:                xs->error = XS_DRIVER_STUFFUP;
                    247:                break;
                    248:        }
                    249:
                    250:        if (xs->error != XS_NOERROR) {
                    251:                /* Don't clobber any existing error state */
                    252:        } else if ((scb->flags & SCB_SENSE) != 0) {
                    253:                /*
                    254:                 * We performed autosense retrieval.
                    255:                 *
                    256:                 * Zero any sense not transferred by the
                    257:                 * device.  The SCSI spec mandates that any
                    258:                 * untransfered data should be assumed to be
                    259:                 * zero.  Complete the 'bounce' of sense information
                    260:                 * through buffers accessible via bus-space by
                    261:                 * copying it into the clients csio.
                    262:                 */
                    263:                memset(&xs->sense, 0, sizeof(struct scsi_sense_data));
                    264:                memcpy(&xs->sense, ahd_get_sense_buf(ahd, scb),
                    265:                    sizeof(struct scsi_sense_data));
                    266:                xs->error = XS_SENSE;
                    267:        } else if ((scb->flags & SCB_PKT_SENSE) != 0) {
                    268:                struct scsi_status_iu_header *siu;
                    269:                u_int32_t len;
                    270:
                    271:                siu = (struct scsi_status_iu_header *)scb->sense_data;
                    272:                len = SIU_SENSE_LENGTH(siu);
                    273:                memset(&xs->sense, 0, sizeof(xs->sense));
                    274:                memcpy(&xs->sense, SIU_SENSE_DATA(siu),
                    275:                    ulmin(len, sizeof(xs->sense)));
                    276:                xs->error = XS_SENSE;
                    277:        }
                    278:
                    279:        ahd_lock(ahd, &s);
                    280:        ahd_free_scb(ahd, scb);
                    281:        ahd_unlock(ahd, &s);
                    282:
                    283:        xs->flags |= ITSDONE;
                    284:        scsi_done(xs);
                    285: }
                    286:
                    287: void
                    288: ahd_minphys(struct buf *bp)
                    289: {
                    290:        /*
                    291:         * Even though the card can transfer up to 16megs per command
                    292:         * we are limited by the number of segments in the dma segment
                    293:         * list that we can hold.  The worst case is that all pages are
                    294:         * discontinuous physically, hence the "page per segment" limit
                    295:         * enforced here.
                    296:         */
                    297:        if (bp->b_bcount > ((AHD_NSEG - 1) * PAGE_SIZE)) {
                    298:                bp->b_bcount = ((AHD_NSEG - 1) * PAGE_SIZE);
                    299:        }
                    300:        minphys(bp);
                    301: }
                    302:
                    303: int32_t
                    304: ahd_action(struct scsi_xfer *xs)
                    305: {
                    306:        struct  ahd_softc *ahd;
                    307:        struct scb *scb;
                    308:        struct hardware_scb *hscb;
                    309:        u_int   target_id;
                    310:        u_int   our_id;
                    311:        int     s;
                    312:        int     dontqueue = 0;
                    313:        struct  ahd_initiator_tinfo *tinfo;
                    314:        struct  ahd_tmode_tstate *tstate;
                    315:        u_int   col_idx;
                    316:        u_int16_t quirks;
                    317:
                    318:        SC_DEBUG(xs->sc_link, SDEV_DB3, ("ahd_action\n"));
                    319:        ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;
                    320:
                    321:        /* determine safety of software queueing */
                    322:        dontqueue = xs->flags & SCSI_POLL;
                    323:
                    324:        target_id = xs->sc_link->target;
                    325:        our_id = SCSI_SCSI_ID(ahd, xs->sc_link);
                    326:
                    327:        if ((ahd->flags & AHD_INITIATORROLE) == 0) {
                    328:                xs->error = XS_DRIVER_STUFFUP;
                    329:                xs->flags |= ITSDONE;
                    330:                scsi_done(xs);
                    331:                return (COMPLETE);
                    332:                /* return       ccb->ccb_h.status = CAM_PROVIDE_FAIL; */
                    333:        }
                    334:        /*
                    335:         * get an scb to use.
                    336:         */
                    337:        ahd_lock(ahd, &s);
                    338:        tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
                    339:
                    340:        quirks = xs->sc_link->quirks;
                    341:
                    342:        if ((quirks & SDEV_NOTAGS) != 0 ||
                    343:            (tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0)
                    344:                col_idx = AHD_NEVER_COL_IDX;
                    345:        else
                    346:                col_idx = AHD_BUILD_COL_IDX(target_id, xs->sc_link->lun);
                    347:
                    348:        if ((scb = ahd_get_scb(ahd, col_idx)) == NULL) {
                    349:                ahd->flags |= AHD_RESOURCE_SHORTAGE;
                    350:                ahd_unlock(ahd, &s);
                    351:                return (TRY_AGAIN_LATER);
                    352:        }
                    353:        ahd_unlock(ahd, &s);
                    354:
                    355:        hscb = scb->hscb;
                    356:
                    357:        SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
                    358:
                    359:        scb->xs = xs;
                    360:        timeout_set(&xs->stimeout, ahd_timeout, scb);
                    361:
                    362:        /*
                    363:         * Put all the arguments for the xfer in the scb
                    364:         */
                    365:        hscb->control = 0;
                    366:        hscb->scsiid = BUILD_SCSIID(ahd, xs->sc_link, target_id, our_id);
                    367:        hscb->lun = xs->sc_link->lun;
                    368:        if (xs->xs_control & XS_CTL_RESET) {
                    369:                hscb->cdb_len = 0;
                    370:                scb->flags |= SCB_DEVICE_RESET;
                    371:                hscb->control |= MK_MESSAGE;
                    372:                hscb->task_management = SIU_TASKMGMT_LUN_RESET;
                    373:                return (ahd_execute_scb(scb, NULL, 0));
                    374:        } else {
                    375:                hscb->task_management = 0;
                    376:                return (ahd_setup_data(ahd, xs, scb));
                    377:        }
                    378: }
                    379:
                    380: int
                    381: ahd_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
                    382: {
                    383:        struct  scb *scb;
                    384:        struct  scsi_xfer *xs;
                    385:        struct  ahd_softc *ahd;
                    386:        struct  ahd_initiator_tinfo *tinfo;
                    387:        struct  ahd_tmode_tstate *tstate;
                    388:        u_int   mask;
                    389:        int     s;
                    390:
                    391:        scb = (struct scb *)arg;
                    392:        xs = scb->xs;
                    393:        xs->error = CAM_REQ_INPROG;
                    394:        xs->status = 0;
                    395:        ahd = (struct ahd_softc *)xs->sc_link->adapter_softc;
                    396:
                    397:        if (nsegments != 0) {
                    398:                void *sg;
                    399:                int op;
                    400:                u_int i;
                    401:
                    402:                ahd_setup_data_scb(ahd, scb);
                    403:
                    404:                /* Copy the segments into our SG list */
                    405:                for (i = nsegments, sg = scb->sg_list; i > 0; i--) {
                    406:
                    407:                        sg = ahd_sg_setup(ahd, scb, sg, dm_segs->ds_addr,
                    408:                                          dm_segs->ds_len,
                    409:                                          /*last*/i == 1);
                    410:                        dm_segs++;
                    411:                }
                    412:
                    413:                if ((xs->flags & SCSI_DATA_IN) != 0)
                    414:                        op = BUS_DMASYNC_PREREAD;
                    415:                else
                    416:                        op = BUS_DMASYNC_PREWRITE;
                    417:
                    418:                bus_dmamap_sync(ahd->parent_dmat, scb->dmamap, 0,
                    419:                                scb->dmamap->dm_mapsize, op);
                    420:
                    421:        }
                    422:
                    423:        ahd_lock(ahd, &s);
                    424:
                    425:        /*
                    426:         * Last time we need to check if this SCB needs to
                    427:         * be aborted.
                    428:         */
                    429:        if (xs->flags & ITSDONE) {
                    430:                if (nsegments != 0)
                    431:                        bus_dmamap_unload(ahd->parent_dmat,
                    432:                                          scb->dmamap);
                    433:                ahd_free_scb(ahd, scb);
                    434:                ahd_unlock(ahd, &s);
                    435:                return (COMPLETE);
                    436:        }
                    437:
                    438:        tinfo = ahd_fetch_transinfo(ahd, SCSIID_CHANNEL(ahd, scb->hscb->scsiid),
                    439:                                    SCSIID_OUR_ID(scb->hscb->scsiid),
                    440:                                    SCSIID_TARGET(ahd, scb->hscb->scsiid),
                    441:                                    &tstate);
                    442:
                    443:        mask = SCB_GET_TARGET_MASK(ahd, scb);
                    444:
                    445:        if ((tstate->discenable & mask) != 0)
                    446:                scb->hscb->control |= DISCENB;
                    447:
                    448:        if ((tstate->tagenable & mask) != 0)
                    449:                scb->hscb->control |= TAG_ENB;
                    450:
                    451:        if ((tinfo->curr.ppr_options & MSG_EXT_PPR_PROT_IUS) != 0) {
                    452:                scb->flags |= SCB_PACKETIZED;
                    453:                if (scb->hscb->task_management != 0)
                    454:                        scb->hscb->control &= ~MK_MESSAGE;
                    455:        }
                    456:
                    457:        if ((tstate->auto_negotiate & mask) != 0) {
                    458:                scb->flags |= SCB_AUTO_NEGOTIATE;
                    459:                scb->hscb->control |= MK_MESSAGE;
                    460:        }
                    461:
                    462:        /* XXX with ahc there was some bus_dmamap_sync(PREREAD|PREWRITE); */
                    463:
                    464:        LIST_INSERT_HEAD(&ahd->pending_scbs, scb, pending_links);
                    465:
                    466:        if (!(xs->flags & SCSI_POLL))
                    467:                timeout_add(&xs->stimeout, (xs->timeout * hz) / 1000);
                    468:
                    469:        scb->flags |= SCB_ACTIVE;
                    470:
                    471:        if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
                    472:                /* Define a mapping from our tag to the SCB. */
                    473:                ahd->scb_data.scbindex[SCB_GET_TAG(scb)] = scb;
                    474:                ahd_pause(ahd);
                    475:                ahd_set_scbptr(ahd, SCB_GET_TAG(scb));
                    476:                ahd_outb(ahd, RETURN_1, CONT_MSG_LOOP_TARG);
                    477:                ahd_unpause(ahd);
                    478:        } else {
                    479:                ahd_queue_scb(ahd, scb);
                    480:        }
                    481:
                    482:        if (!(xs->flags & SCSI_POLL)) {
                    483:                int target = xs->sc_link->target;
                    484:                int lun = SCB_GET_LUN(scb);
                    485:
                    486:                if (ahd->inited_target[target] == 0) {
                    487:                        struct  ahd_devinfo devinfo;
                    488:
                    489:                        ahd_adapter_req_set_xfer_mode(ahd, scb);
                    490:                        ahd_compile_devinfo(&devinfo, ahd->our_id, target, lun,
                    491:                            'A', /*XXX milos*/ROLE_UNKNOWN);
                    492:                        ahd_scb_devinfo(ahd, &devinfo, scb);
                    493:                        ahd_update_neg_request(ahd, &devinfo, tstate, tinfo,
                    494:                                AHD_NEG_IF_NON_ASYNC);
                    495:                        ahd->inited_target[target] = 1;
                    496:                }
                    497:
                    498:                ahd_unlock(ahd, &s);
                    499:                return (SUCCESSFULLY_QUEUED);
                    500:        }
                    501:
                    502:        /*
                    503:         * If we can't use interrupts, poll for completion
                    504:         */
                    505:        SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
                    506:
                    507:        do {
                    508:                if (ahd_poll(ahd, xs->timeout)) {
                    509:                        if (!(xs->flags & SCSI_SILENT))
                    510:                                printf("cmd fail\n");
                    511:                        ahd_timeout(scb);
                    512:                        break;
                    513:                }
                    514:        } while (!(xs->flags & ITSDONE));
                    515:
                    516:        ahd_unlock(ahd, &s);
                    517:        return (COMPLETE);
                    518: }
                    519:
                    520: int
                    521: ahd_poll(struct ahd_softc *ahd, int wait)
                    522: {
                    523:        while (--wait) {
                    524:                DELAY(1000);
                    525:                if (ahd_inb(ahd, INTSTAT) & INT_PEND)
                    526:                        break;
                    527:        }
                    528:
                    529:        if (wait == 0) {
                    530:                printf("%s: board is not responding\n", ahd_name(ahd));
                    531:                return (EIO);
                    532:        }
                    533:
                    534:        ahd_intr((void *)ahd);
                    535:        return (0);
                    536: }
                    537:
                    538: int
                    539: ahd_setup_data(struct ahd_softc *ahd, struct scsi_xfer *xs,
                    540:               struct scb *scb)
                    541: {
                    542:        struct hardware_scb *hscb;
                    543:        int s;
                    544:
                    545:        hscb = scb->hscb;
                    546:        xs->resid = xs->status = 0;
                    547:        xs->error = CAM_REQ_INPROG;
                    548:
                    549:        hscb->cdb_len = xs->cmdlen;
                    550:        if (hscb->cdb_len > MAX_CDB_LEN) {
                    551:                ahd_lock(ahd, &s);
                    552:                ahd_free_scb(ahd, scb);
                    553:                ahd_unlock(ahd, &s);
                    554:                xs->error = XS_DRIVER_STUFFUP;
                    555:                xs->flags |= ITSDONE;
                    556:                scsi_done(xs);
                    557:                return (COMPLETE);
                    558:        }
                    559:
                    560:        memcpy(hscb->shared_data.idata.cdb, xs->cmd, hscb->cdb_len);
                    561:
                    562:        /* Only use S/G if there is a transfer */
                    563:        if (xs->datalen) {
                    564:                int error;
                    565:
                    566:                error = bus_dmamap_load(ahd->parent_dmat,
                    567:                                        scb->dmamap, xs->data,
                    568:                                        xs->datalen, NULL,
                    569:                                        ((xs->flags & SCSI_NOSLEEP) ?
                    570:                                        BUS_DMA_NOWAIT : BUS_DMA_WAITOK) |
                    571:                                        BUS_DMA_STREAMING |
                    572:                                        ((xs->flags & XS_CTL_DATA_IN) ?
                    573:                                        BUS_DMA_READ : BUS_DMA_WRITE));
                    574:                if (error) {
                    575: #ifdef AHD_DEBUG
                    576:                        printf("%s: in ahd_setup_data(): bus_dmamap_load() "
                    577:                            "= %d\n", ahd_name(ahd), error);
                    578: #endif
                    579:                        ahd_lock(ahd, &s);
                    580:                        ahd_free_scb(ahd, scb);
                    581:                        ahd_unlock(ahd, &s);
                    582:                        return (TRY_AGAIN_LATER);       /* XXX fvdl */
                    583:                }
                    584:                error = ahd_execute_scb(scb, scb->dmamap->dm_segs,
                    585:                    scb->dmamap->dm_nsegs);
                    586:                return error;
                    587:        } else {
                    588:                return ahd_execute_scb(scb, NULL, 0);
                    589:        }
                    590: }
                    591:
                    592: void
                    593: ahd_platform_set_tags(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
                    594:     ahd_queue_alg alg)
                    595: {
                    596:        struct ahd_tmode_tstate *tstate;
                    597:
                    598:        ahd_fetch_transinfo(ahd, devinfo->channel, devinfo->our_scsiid,
                    599:            devinfo->target, &tstate);
                    600:
                    601:        if (alg != AHD_QUEUE_NONE)
                    602:                tstate->tagenable |= devinfo->target_mask;
                    603:        else
                    604:                tstate->tagenable &= ~devinfo->target_mask;
                    605: }
                    606:
                    607: int
                    608: ahd_platform_alloc(struct ahd_softc *ahd, void *platform_arg)
                    609: {
                    610:        if (sizeof(struct ahd_platform_data) > 0) {
                    611:                ahd->platform_data = malloc(sizeof(struct ahd_platform_data),
                    612:                    M_DEVBUF, M_NOWAIT);
                    613:                if (ahd->platform_data == NULL)
                    614:                        return (ENOMEM);
                    615:                bzero(ahd->platform_data, sizeof(struct ahd_platform_data));
                    616:        }
                    617:
                    618:        return (0);
                    619: }
                    620:
                    621: void
                    622: ahd_platform_free(struct ahd_softc *ahd)
                    623: {
                    624:        if (sizeof(struct ahd_platform_data) > 0)
                    625:                free(ahd->platform_data, M_DEVBUF);
                    626: }
                    627:
                    628: int
                    629: ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd)
                    630: {
                    631:        /* We don't sort softcs under OpenBSD so report equal always */
                    632:        return (0);
                    633: }
                    634:
                    635: int
                    636: ahd_detach(struct device *self, int flags)
                    637: {
                    638:        int rv = 0;
                    639:
                    640:        struct ahd_softc *ahd = (struct ahd_softc*)self;
                    641:
                    642:        if (ahd->sc_child != NULL)
                    643:                rv = config_detach((void *)ahd->sc_child, flags);
                    644:
                    645:        if (ahd->shutdown_hook != NULL)
                    646:                shutdownhook_disestablish(ahd->shutdown_hook);
                    647:
                    648:        ahd_free(ahd);
                    649:
                    650:        return rv;
                    651: }
                    652:
                    653: void
                    654: ahd_adapter_req_set_xfer_mode(struct ahd_softc *ahd, struct scb *scb)
                    655: {
                    656:        struct ahd_initiator_tinfo *tinfo;
                    657:        struct ahd_tmode_tstate *tstate;
                    658:        int target_id, our_id;
                    659:        struct ahd_devinfo devinfo;
                    660:        u_int16_t quirks;
                    661:        u_int width, ppr_options, period, offset;
                    662:        int s;
                    663:
                    664:        target_id = scb->xs->sc_link->target;
                    665:        our_id = SCSI_SCSI_ID(ahd, scb->xs->sc_link);
                    666:
                    667:        s = splbio();
                    668:
                    669:        quirks = scb->xs->sc_link->quirks;
                    670:        tinfo = ahd_fetch_transinfo(ahd, 'A', our_id, target_id, &tstate);
                    671:        ahd_compile_devinfo(&devinfo, our_id, target_id, 0, 'A',
                    672:            ROLE_INITIATOR);
                    673:
                    674:        tstate->discenable |= (ahd->user_discenable & devinfo.target_mask);
                    675:
                    676:        if (quirks & SDEV_NOTAGS)
                    677:                tstate->tagenable &= ~devinfo.target_mask;
                    678:        else if (ahd->user_tagenable & devinfo.target_mask)
                    679:                tstate->tagenable |= devinfo.target_mask;
                    680:
                    681:        if (quirks & SDEV_NOWIDE)
                    682:                width = MSG_EXT_WDTR_BUS_8_BIT;
                    683:        else
                    684:                width = MSG_EXT_WDTR_BUS_16_BIT;
                    685:
                    686:        ahd_validate_width(ahd, NULL, &width, ROLE_UNKNOWN);
                    687:        if (width > tinfo->user.width)
                    688:                width = tinfo->user.width;
                    689:        ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);
                    690:
                    691:        if (quirks & SDEV_NOSYNC) {
                    692:                period = 0;
                    693:                offset = 0;
                    694:        } else {
                    695:                period = tinfo->user.period;
                    696:                offset = tinfo->user.offset;
                    697:        }
                    698:
                    699:        /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */
                    700:        ppr_options = tinfo->user.ppr_options;
                    701:        /* XXX Other reasons to avoid ppr? XXX */
                    702:        if (width < MSG_EXT_WDTR_BUS_16_BIT)
                    703:                ppr_options = 0;
                    704:
                    705:        if ((tstate->discenable & devinfo.target_mask) == 0 ||
                    706:            (tstate->tagenable & devinfo.target_mask) == 0)
                    707:                ppr_options &= ~MSG_EXT_PPR_PROT_IUS;
                    708:
                    709:        ahd_find_syncrate(ahd, &period, &ppr_options, AHD_SYNCRATE_MAX);
                    710:        ahd_validate_offset(ahd, NULL, period, &offset, width, ROLE_UNKNOWN);
                    711:
                    712:        if (offset == 0) {
                    713:                period = 0;
                    714:                ppr_options = 0;
                    715:        }
                    716:
                    717:        if (ppr_options != 0 && tinfo->user.transport_version >= 3) {
                    718:                tinfo->goal.transport_version = tinfo->user.transport_version;
                    719:                tinfo->curr.transport_version = tinfo->user.transport_version;
                    720:        }
                    721:
                    722:        ahd_set_syncrate(ahd, &devinfo, period, offset, ppr_options,
                    723:                AHD_TRANS_GOAL, FALSE);
                    724:
                    725:        splx(s);
                    726: }
                    727:
                    728: void
                    729: aic_timer_reset(aic_timer_t *timer, u_int msec, ahd_callback_t *func,
                    730:     void *arg)
                    731: {
                    732:        uint64_t ticks;
                    733:
                    734:        ticks = msec;
                    735:        ticks *= hz;
                    736:        ticks /= 1000;
                    737:        callout_reset(timer, ticks, func, arg);
                    738: }
                    739:
                    740: void
                    741: aic_scb_timer_reset(struct scb *scb, u_int msec)
                    742: {
                    743:        uint64_t ticks;
                    744:
                    745:        ticks = msec;
                    746:        ticks *= hz;
                    747:        ticks /= 1000;
                    748:        if (!(scb->xs->xs_control & XS_CTL_POLL))
                    749:                callout_reset(&scb->xs->xs_callout, ticks, ahd_timeout, scb);
                    750: }
                    751:
                    752: void
                    753: ahd_flush_device_writes(struct ahd_softc *ahd)
                    754: {
                    755:        /* XXX Is this sufficient for all architectures??? */
                    756:        ahd_inb(ahd, INTSTAT);
                    757: }
                    758:
                    759: void
                    760: aic_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
                    761: {
                    762:        int s;
                    763:
                    764:        ahd_lock(ahd, &s);
                    765:
                    766:        if ((ahd->flags & AHD_RESOURCE_SHORTAGE) != 0) {
                    767:                ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
                    768:        }
                    769:
                    770:        if (!cold) {
                    771:                /* we are no longer in autoconf */
                    772:                timeout_del(&scb->xs->stimeout);
                    773:        }
                    774:
                    775:        ahd_unlock(ahd, &s);
                    776: }
                    777:
                    778: void
                    779: ahd_print_path(struct ahd_softc *ahd, struct scb *scb)
                    780: {
                    781:        sc_print_addr(scb->xs->sc_link);
                    782: }
                    783:
                    784: void
                    785: ahd_platform_dump_card_state(struct ahd_softc *ahd)
                    786: {
                    787:        /* Nothing to do here for OpenBSD */
                    788:        printf("FEATURES = 0x%x, FLAGS = 0x%x, CHIP = 0x%x BUGS =0x%x\n",
                    789:                ahd->features, ahd->flags, ahd->chip, ahd->bugs);
                    790: }
                    791:
                    792: void
                    793: ahd_platform_flushwork(struct ahd_softc *ahd)
                    794: {
                    795: }

CVSweb