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

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

1.1       nbrk        1: /*     $OpenBSD: aic7xxx_openbsd.c,v 1.35 2007/08/04 14:37:34 krw Exp $        */
                      2: /*     $NetBSD: aic7xxx_osm.c,v 1.14 2003/11/02 11:07:44 wiz Exp $     */
                      3:
                      4: /*
                      5:  * Bus independent OpenBSD shim for the aic7xxx based adaptec SCSI controllers
                      6:  *
                      7:  * Copyright (c) 1994-2001 Justin T. Gibbs.
                      8:  * Copyright (c) 2001-2002 Steve Murphree, Jr.
                      9:  * All rights reserved.
                     10:  *
                     11:  * Redistribution and use in source and binary forms, with or without
                     12:  * modification, are permitted provided that the following conditions
                     13:  * are met:
                     14:  * 1. Redistributions of source code must retain the above copyright
                     15:  *    notice, this list of conditions, and the following disclaimer,
                     16:  *    without modification.
                     17:  * 2. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission.
                     19:  *
                     20:  * Alternatively, this software may be distributed under the terms of the
                     21:  * GNU Public License ("GPL").
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
                     27:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  *
                     35:  * //depot/aic7xxx/freebsd/dev/aic7xxx/aic7xxx_osm.c#12 $
                     36:  *
                     37:  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_osm.c,v 1.31 2002/11/30 19:08:58 scottl Exp $
                     38:  */
                     39: /*
                     40:  * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc. - April 2003
                     41:  */
                     42:
                     43: #include <sys/cdefs.h>
                     44: /* __KERNEL_RCSID(0, "$NetBSD: aic7xxx_osm.c,v 1.14 2003/11/02 11:07:44 wiz Exp $"); */
                     45:
                     46: #include <dev/ic/aic7xxx_openbsd.h>
                     47: #include <dev/ic/aic7xxx_inline.h>
                     48:
                     49: #ifndef AHC_TMODE_ENABLE
                     50: #define AHC_TMODE_ENABLE 0
                     51: #endif
                     52:
                     53:
                     54: int    ahc_action(struct scsi_xfer *);
                     55: int    ahc_execute_scb(void *, bus_dma_segment_t *, int);
                     56: int    ahc_poll(struct ahc_softc *, int);
                     57: int    ahc_setup_data(struct ahc_softc *, struct scsi_xfer *, struct scb *);
                     58:
                     59: void   ahc_minphys(struct buf *);
                     60: void   ahc_adapter_req_set_xfer_mode(struct ahc_softc *, struct scb *);
                     61:
                     62:
                     63: struct cfdriver ahc_cd = {
                     64:        NULL, "ahc", DV_DULL
                     65: };
                     66:
                     67: static struct scsi_adapter ahc_switch =
                     68: {
                     69:        ahc_action,
                     70:        ahc_minphys,
                     71:        0,
                     72:        0,
                     73: };
                     74:
                     75: /* the below structure is so we have a default dev struct for our link struct */
                     76: static struct scsi_device ahc_dev =
                     77: {
                     78:        NULL, /* Use default error handler */
                     79:        NULL, /* have a queue, served by this */
                     80:        NULL, /* have no async handler */
                     81:        NULL, /* Use default 'done' routine */
                     82: };
                     83:
                     84: /*
                     85:  * Attach all the sub-devices we can find
                     86:  */
                     87: int
                     88: ahc_attach(struct ahc_softc *ahc)
                     89: {
                     90:        struct scsibus_attach_args saa;
                     91:        int s;
                     92:
                     93:         s = splbio();
                     94:
                     95:        /*
                     96:         * fill in the prototype scsi_links.
                     97:         */
                     98:        ahc->sc_channel.adapter_target = ahc->our_id;
                     99:        if (ahc->features & AHC_WIDE)
                    100:                ahc->sc_channel.adapter_buswidth = 16;
                    101:        ahc->sc_channel.adapter_softc = ahc;
                    102:        ahc->sc_channel.adapter = &ahc_switch;
                    103:        ahc->sc_channel.openings = 16;
                    104:        ahc->sc_channel.device = &ahc_dev;
                    105:
                    106:        if (ahc->features & AHC_TWIN) {
                    107:                /* Configure the second scsi bus */
                    108:                ahc->sc_channel_b = ahc->sc_channel;
                    109:                ahc->sc_channel_b.adapter_target = ahc->our_id_b;
                    110:        }
                    111:
                    112: #ifndef DEBUG
                    113:        if (bootverbose) {
                    114:                char ahc_info[256];
                    115:                ahc_controller_info(ahc, ahc_info, sizeof ahc_info);
                    116:                printf("%s: %s\n", ahc->sc_dev.dv_xname, ahc_info);
                    117:        }
                    118: #endif
                    119:
                    120:        ahc_intr_enable(ahc, TRUE);
                    121:
                    122:        if (ahc->flags & AHC_RESET_BUS_A)
                    123:                ahc_reset_channel(ahc, 'A', TRUE);
                    124:        if ((ahc->features & AHC_TWIN) && ahc->flags & AHC_RESET_BUS_B)
                    125:                ahc_reset_channel(ahc, 'B', TRUE);
                    126:
                    127:        bzero(&saa, sizeof(saa));
                    128:        if ((ahc->flags & AHC_PRIMARY_CHANNEL) == 0) {
                    129:                saa.saa_sc_link = &ahc->sc_channel;
                    130:                ahc->sc_child = config_found((void *)&ahc->sc_dev,
                    131:                    &saa, scsiprint);
                    132:                if (ahc->features & AHC_TWIN) {
                    133:                        saa.saa_sc_link = &ahc->sc_channel_b;
                    134:                        ahc->sc_child_b = config_found((void *)&ahc->sc_dev,
                    135:                            &saa, scsiprint);
                    136:                }
                    137:        } else {
                    138:                if (ahc->features & AHC_TWIN) {
                    139:                        saa.saa_sc_link = &ahc->sc_channel_b;
                    140:                        ahc->sc_child = config_found((void *)&ahc->sc_dev,
                    141:                            &saa, scsiprint);
                    142:                }
                    143:                saa.saa_sc_link = &ahc->sc_channel;
                    144:                ahc->sc_child_b = config_found((void *)&ahc->sc_dev,
                    145:                    &saa, scsiprint);
                    146:        }
                    147:
                    148:        splx(s);
                    149:        return (1);
                    150: }
                    151:
                    152: /*
                    153:  * Catch an interrupt from the adapter
                    154:  */
                    155: int
                    156: ahc_platform_intr(void *arg)
                    157: {
                    158:        struct  ahc_softc *ahc = (struct ahc_softc *)arg;
                    159:
                    160:        bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
                    161:            0, ahc->scb_data->hscb_dmamap->dm_mapsize,
                    162:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                    163:
                    164:        return ahc_intr(ahc);
                    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: ahc_done(struct ahc_softc *ahc, struct scb *scb)
                    174: {
                    175:        struct scsi_xfer *xs = scb->xs;
                    176:        int s;
                    177:
                    178:        bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
                    179:            0, ahc->scb_data->hscb_dmamap->dm_mapsize,
                    180:            BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
                    181:
                    182:        LIST_REMOVE(scb, pending_links);
                    183:        if ((scb->flags & SCB_UNTAGGEDQ) != 0) {
                    184:                struct scb_tailq *untagged_q;
                    185:                int target_offset;
                    186:
                    187:                target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
                    188:                untagged_q = &ahc->untagged_queues[target_offset];
                    189:                TAILQ_REMOVE(untagged_q, scb, links.tqe);
                    190:                scb->flags &= ~SCB_UNTAGGEDQ;
                    191:                ahc_run_untagged_queue(ahc, untagged_q);
                    192:        }
                    193:
                    194:        timeout_del(&xs->stimeout);
                    195:
                    196:        if (xs->datalen) {
                    197:                int op;
                    198:
                    199:                if ((xs->flags & SCSI_DATA_IN) != 0)
                    200:                        op = BUS_DMASYNC_POSTREAD;
                    201:                else
                    202:                        op = BUS_DMASYNC_POSTWRITE;
                    203:                bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0,
                    204:                                scb->dmamap->dm_mapsize, op);
                    205:                bus_dmamap_unload(ahc->parent_dmat, scb->dmamap);
                    206:        }
                    207:
                    208:        /* Translate the CAM status code to a SCSI error code. */
                    209:        switch (xs->error) {
                    210:        case CAM_SCSI_STATUS_ERROR:
                    211:        case CAM_REQ_INPROG:
                    212:        case CAM_REQ_CMP:
                    213:                switch (xs->status) {
                    214:                case SCSI_TASKSET_FULL:
                    215:                        /* SCSI Layer won't requeue, so we force infinite
                    216:                         * retries until queue space is available. XS_BUSY
                    217:                         * is dangerous because if the NOSLEEP flag is set
                    218:                         * it can cause the I/O to return EIO. XS_BUSY code
                    219:                         * falls through to XS_TIMEOUT anyway.
                    220:                         */
                    221:                        xs->error = XS_TIMEOUT;
                    222:                        xs->retries++;
                    223:                        break;
                    224:                case SCSI_BUSY:
                    225:                        xs->error = XS_BUSY;
                    226:                        break;
                    227:                case SCSI_CHECK:
                    228:                case SCSI_TERMINATED:
                    229:                        if ((scb->flags & SCB_SENSE) == 0) {
                    230:                                /* CHECK on CHECK? */
                    231:                                xs->error = XS_DRIVER_STUFFUP;
                    232:                        } else
                    233:                                xs->error = XS_NOERROR;
                    234:                        break;
                    235:                default:
                    236:                        xs->error = XS_NOERROR;
                    237:                        break;
                    238:                }
                    239:                break;
                    240:        case CAM_BUSY:
                    241:                xs->error = XS_BUSY;
                    242:                break;
                    243:        case CAM_CMD_TIMEOUT:
                    244:                xs->error = XS_TIMEOUT;
                    245:                break;
                    246:        case CAM_BDR_SENT:
                    247:        case CAM_SCSI_BUS_RESET:
                    248:                xs->error = XS_RESET;
                    249:                break;
                    250:        case CAM_REQUEUE_REQ:
                    251:                xs->error = XS_TIMEOUT;
                    252:                xs->retries++;
                    253:                break;
                    254:        case CAM_SEL_TIMEOUT:
                    255:                xs->error = XS_SELTIMEOUT;
                    256:                break;
                    257:        default:
                    258:                xs->error = XS_DRIVER_STUFFUP;
                    259:                break;
                    260:        }
                    261:
                    262:        /* Don't clobber any existing error state */
                    263:        if (xs->error != XS_NOERROR) {
                    264:          /* Don't clobber any existing error state */
                    265:        } else if ((scb->flags & SCB_SENSE) != 0) {
                    266:                /*
                    267:                 * We performed autosense retrieval.
                    268:                 *
                    269:                 * Zero any sense not transferred by the
                    270:                 * device.  The SCSI spec mandates that any
                    271:                 * untransferred data should be assumed to be
                    272:                 * zero.  Complete the 'bounce' of sense information
                    273:                 * through buffers accessible via bus-space by
                    274:                 * copying it into the clients csio.
                    275:                 */
                    276:                memset(&xs->sense, 0, sizeof(struct scsi_sense_data));
                    277:                memcpy(&xs->sense, ahc_get_sense_buf(ahc, scb),
                    278:                    aic_le32toh(scb->sg_list->len) & AHC_SG_LEN_MASK);
                    279:                xs->error = XS_SENSE;
                    280:        }
                    281:
                    282:         s = splbio();
                    283:        ahc_free_scb(ahc, scb);
                    284:         splx(s);
                    285:
                    286:        xs->flags |= ITSDONE;
                    287:        scsi_done(xs);
                    288: }
                    289:
                    290: void
                    291: ahc_minphys(bp)
                    292:        struct buf *bp;
                    293: {
                    294:        /*
                    295:         * Even though the card can transfer up to 16megs per command
                    296:         * we are limited by the number of segments in the dma segment
                    297:         * list that we can hold.  The worst case is that all pages are
                    298:         * discontinuous physically, hence the "page per segment" limit
                    299:         * enforced here.
                    300:         */
                    301:        if (bp->b_bcount > ((AHC_NSEG - 1) * PAGE_SIZE)) {
                    302:                bp->b_bcount = ((AHC_NSEG - 1) * PAGE_SIZE);
                    303:        }
                    304:        minphys(bp);
                    305: }
                    306:
                    307: int32_t
                    308: ahc_action(struct scsi_xfer *xs)
                    309: {
                    310:        struct ahc_softc *ahc;
                    311:        struct scb *scb;
                    312:        struct hardware_scb *hscb;
                    313:        u_int target_id;
                    314:        u_int our_id;
                    315:        int s;
                    316:        int dontqueue = 0;
                    317:
                    318:        SC_DEBUG(xs->sc_link, SDEV_DB3, ("ahc_action\n"));
                    319:        ahc = (struct ahc_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(ahc, xs->sc_link);
                    326:
                    327:        /*
                    328:         * get an scb to use.
                    329:         */
                    330:        s = splbio();
                    331:        if ((scb = ahc_get_scb(ahc)) == NULL) {
                    332:                splx(s);
                    333:                return (TRY_AGAIN_LATER);
                    334:        }
                    335:        splx(s);
                    336:
                    337:        hscb = scb->hscb;
                    338:
                    339:        SC_DEBUG(xs->sc_link, SDEV_DB3, ("start scb(%p)\n", scb));
                    340:        scb->xs = xs;
                    341:        timeout_set(&xs->stimeout, ahc_timeout, scb);
                    342:
                    343:        /*
                    344:         * Put all the arguments for the xfer in the scb
                    345:         */
                    346:        hscb->control = 0;
                    347:        hscb->scsiid = BUILD_SCSIID(ahc, xs->sc_link, target_id, our_id);
                    348:        hscb->lun = xs->sc_link->lun;
                    349:        if (xs->xs_control & XS_CTL_RESET) {
                    350:                hscb->cdb_len = 0;
                    351:                scb->flags |= SCB_DEVICE_RESET;
                    352:                hscb->control |= MK_MESSAGE;
                    353:                return (ahc_execute_scb(scb, NULL, 0));
                    354:        }
                    355:
                    356:        return (ahc_setup_data(ahc, xs, scb));
                    357: }
                    358:
                    359: int
                    360: ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments)
                    361: {
                    362:        struct  scb *scb;
                    363:        struct  scsi_xfer *xs;
                    364:        struct  ahc_softc *ahc;
                    365:        struct  ahc_initiator_tinfo *tinfo;
                    366:        struct  ahc_tmode_tstate *tstate;
                    367:
                    368:        u_int   mask;
                    369:        int     s;
                    370:
                    371:        scb = (struct scb *)arg;
                    372:        xs = scb->xs;
                    373:        xs->error = CAM_REQ_INPROG;
                    374:        xs->status = 0;
                    375:        ahc = (struct ahc_softc *)xs->sc_link->adapter_softc;
                    376:
                    377:        if (nsegments != 0) {
                    378:                struct    ahc_dma_seg *sg;
                    379:                bus_dma_segment_t *end_seg;
                    380:                int op;
                    381:
                    382:                end_seg = dm_segs + nsegments;
                    383:
                    384:                /* Copy the segments into our SG list */
                    385:                sg = scb->sg_list;
                    386:                while (dm_segs < end_seg) {
                    387:                        uint32_t len;
                    388:
                    389:                        sg->addr = aic_htole32(dm_segs->ds_addr);
                    390:                        len = dm_segs->ds_len
                    391:                            | ((dm_segs->ds_addr >> 8) & 0x7F000000);
                    392:                        sg->len = aic_htole32(len);
                    393:                        sg++;
                    394:                        dm_segs++;
                    395:                }
                    396:
                    397:                /*
                    398:                 * Note where to find the SG entries in bus space.
                    399:                 * We also set the full residual flag which the
                    400:                 * sequencer will clear as soon as a data transfer
                    401:                 * occurs.
                    402:                 */
                    403:                scb->hscb->sgptr = aic_htole32(scb->sg_list_phys|SG_FULL_RESID);
                    404:
                    405:                if ((xs->flags & SCSI_DATA_IN) != 0)
                    406:                        op = BUS_DMASYNC_PREREAD;
                    407:                else
                    408:                        op = BUS_DMASYNC_PREWRITE;
                    409:
                    410:                bus_dmamap_sync(ahc->parent_dmat, scb->dmamap, 0,
                    411:                                scb->dmamap->dm_mapsize, op);
                    412:
                    413:                sg--;
                    414:                sg->len |= aic_htole32(AHC_DMA_LAST_SEG);
                    415:
                    416:                bus_dmamap_sync(ahc->parent_dmat, scb->sg_map->sg_dmamap,
                    417:                    0, scb->sg_map->sg_dmamap->dm_mapsize,
                    418:                    BUS_DMASYNC_PREWRITE);
                    419:
                    420:                /* Copy the first SG into the "current" data pointer area */
                    421:                scb->hscb->dataptr = scb->sg_list->addr;
                    422:                scb->hscb->datacnt = scb->sg_list->len;
                    423:        } else {
                    424:                scb->hscb->sgptr = aic_htole32(SG_LIST_NULL);
                    425:                scb->hscb->dataptr = 0;
                    426:                scb->hscb->datacnt = 0;
                    427:        }
                    428:
                    429:        scb->sg_count = nsegments;
                    430:
                    431:        s = splbio();
                    432:
                    433:        /*
                    434:         * Last time we need to check if this SCB needs to
                    435:         * be aborted.
                    436:         */
                    437:        if (xs->flags & ITSDONE) {
                    438:                if (nsegments != 0)
                    439:                        bus_dmamap_unload(ahc->parent_dmat, scb->dmamap);
                    440:
                    441:                ahc_free_scb(ahc, scb);
                    442:                splx(s);
                    443:                return (COMPLETE);
                    444:        }
                    445:
                    446:        tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid),
                    447:                                    SCSIID_OUR_ID(scb->hscb->scsiid),
                    448:                                    SCSIID_TARGET(ahc, scb->hscb->scsiid),
                    449:                                    &tstate);
                    450:
                    451:        mask = SCB_GET_TARGET_MASK(ahc, scb);
                    452:        scb->hscb->scsirate = tinfo->scsirate;
                    453:        scb->hscb->scsioffset = tinfo->curr.offset;
                    454:
                    455:        if ((tstate->ultraenb & mask) != 0)
                    456:                scb->hscb->control |= ULTRAENB;
                    457:
                    458:        if ((tstate->discenable & mask) != 0)
                    459:                scb->hscb->control |= DISCENB;
                    460:
                    461:        if ((tstate->auto_negotiate & mask) != 0) {
                    462:                scb->flags |= SCB_AUTO_NEGOTIATE;
                    463:                scb->hscb->control |= MK_MESSAGE;
                    464:        }
                    465:
                    466:        if ((tstate->tagenable & mask) != 0)
                    467:                scb->hscb->control |= TAG_ENB;
                    468:
                    469:        bus_dmamap_sync(ahc->parent_dmat, ahc->scb_data->hscb_dmamap,
                    470:            0, ahc->scb_data->hscb_dmamap->dm_mapsize,
                    471:            BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
                    472:
                    473:        LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
                    474:
                    475:        if (!(xs->flags & SCSI_POLL))
                    476:                timeout_add(&xs->stimeout, (xs->timeout * hz) / 1000);
                    477:
                    478:        /*
                    479:         * We only allow one untagged transaction
                    480:         * per target in the initiator role unless
                    481:         * we are storing a full busy target *lun*
                    482:         * table in SCB space.
                    483:         *
                    484:         * This really should not be of any
                    485:         * concern, as we take care to avoid this
                    486:         * in ahc_done().  XXX smurph
                    487:         */
                    488:        if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0
                    489:            && (ahc->flags & AHC_SCB_BTT) == 0) {
                    490:                struct scb_tailq *untagged_q;
                    491:                int target_offset;
                    492:
                    493:                target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
                    494:                untagged_q = &(ahc->untagged_queues[target_offset]);
                    495:                TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
                    496:                scb->flags |= SCB_UNTAGGEDQ;
                    497:                if (TAILQ_FIRST(untagged_q) != scb) {
                    498:                        if (xs->flags & SCSI_POLL)
                    499:                                goto poll;
                    500:                        else {
                    501:                                splx(s);
                    502:                                return (SUCCESSFULLY_QUEUED);
                    503:                        }
                    504:                }
                    505:        }
                    506:        scb->flags |= SCB_ACTIVE;
                    507:
                    508:        if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
                    509:                /* Define a mapping from our tag to the SCB. */
                    510:                ahc->scb_data->scbindex[scb->hscb->tag] = scb;
                    511:                ahc_pause(ahc);
                    512:                if ((ahc->flags & AHC_PAGESCBS) == 0)
                    513:                        ahc_outb(ahc, SCBPTR, scb->hscb->tag);
                    514:                ahc_outb(ahc, TARG_IMMEDIATE_SCB, scb->hscb->tag);
                    515:                ahc_unpause(ahc);
                    516:        } else {
                    517:                ahc_queue_scb(ahc, scb);
                    518:        }
                    519:
                    520:        if (!(xs->flags & SCSI_POLL)) {
                    521:                if (ahc->inited_target[xs->sc_link->target] == 0) {
                    522:                        struct  ahc_devinfo devinfo;
                    523:
                    524:                        ahc_adapter_req_set_xfer_mode(ahc, scb);
                    525:                        ahc_scb_devinfo(ahc, &devinfo, scb);
                    526:                        ahc_update_neg_request(ahc, &devinfo, tstate, tinfo,
                    527:                            AHC_NEG_IF_NON_ASYNC);
                    528:
                    529:                        ahc->inited_target[xs->sc_link->target] = 1;
                    530:                }
                    531:                splx(s);
                    532:                return (SUCCESSFULLY_QUEUED);
                    533:        }
                    534:
                    535:        /*
                    536:         * If we can't use interrupts, poll for completion
                    537:         */
                    538: poll:
                    539:        SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd_poll\n"));
                    540:
                    541:        do {
                    542:                if (ahc_poll(ahc, xs->timeout)) {
                    543:                        if (!(xs->flags & SCSI_SILENT))
                    544:                                printf("cmd fail\n");
                    545:                        ahc_timeout(scb);
                    546:                        break;
                    547:                }
                    548:        } while (!(xs->flags & ITSDONE));
                    549:
                    550:        splx(s);
                    551:        return (COMPLETE);
                    552: }
                    553:
                    554: int
                    555: ahc_poll(struct ahc_softc *ahc, int wait)
                    556: {
                    557:        while (--wait) {
                    558:                DELAY(1000);
                    559:                if (ahc_inb(ahc, INTSTAT) & INT_PEND)
                    560:                        break;
                    561:        }
                    562:
                    563:        if (wait == 0) {
                    564:                printf("%s: board is not responding\n", ahc_name(ahc));
                    565:                return (EIO);
                    566:        }
                    567:
                    568:        ahc_intr((void *)ahc);
                    569:        return (0);
                    570: }
                    571:
                    572: int
                    573: ahc_setup_data(struct ahc_softc *ahc, struct scsi_xfer *xs,
                    574:               struct scb *scb)
                    575: {
                    576:        struct hardware_scb *hscb;
                    577:        int s;
                    578:
                    579:        hscb = scb->hscb;
                    580:        xs->resid = xs->status = 0;
                    581:        xs->error = CAM_REQ_INPROG;
                    582:
                    583:        hscb->cdb_len = xs->cmdlen;
                    584:        if (hscb->cdb_len > sizeof(hscb->cdb32)) {
                    585:                s = splbio();
                    586:                ahc_free_scb(ahc, scb);
                    587:                splx(s);
                    588:                xs->error = XS_DRIVER_STUFFUP;
                    589:                xs->flags |= ITSDONE;
                    590:                scsi_done(xs);
                    591:                return (COMPLETE);
                    592:        }
                    593:
                    594:        if (hscb->cdb_len > 12) {
                    595:                memcpy(hscb->cdb32, xs->cmd, hscb->cdb_len);
                    596:                scb->flags |= SCB_CDB32_PTR;
                    597:        } else {
                    598:                memcpy(hscb->shared_data.cdb, xs->cmd, hscb->cdb_len);
                    599:        }
                    600:
                    601:        /* Only use S/G if there is a transfer */
                    602:        if (xs->datalen) {
                    603:                int error;
                    604:
                    605:                 error = bus_dmamap_load(ahc->parent_dmat,
                    606:                                        scb->dmamap, xs->data,
                    607:                                        xs->datalen, NULL,
                    608:                                        (xs->flags & SCSI_NOSLEEP) ?
                    609:                                        BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
                    610:                if (error) {
                    611: #ifdef AHC_DEBUG
                    612:                         printf("%s: in ahc_setup_data(): bus_dmamap_load() "
                    613:                               "= %d\n",
                    614:                               ahc_name(ahc), error);
                    615: #endif
                    616:                        s = splbio();
                    617:                        ahc_free_scb(ahc, scb);
                    618:                        splx(s);
                    619:                        return (TRY_AGAIN_LATER);       /* XXX fvdl */
                    620: }
                    621:                error = ahc_execute_scb(scb,
                    622:                                        scb->dmamap->dm_segs,
                    623:                                        scb->dmamap->dm_nsegs);
                    624:                return error;
                    625:        } else {
                    626:                return ahc_execute_scb(scb, NULL, 0);
                    627:        }
                    628: }
                    629:
                    630: void
                    631: ahc_timeout(void *arg)
                    632: {
                    633:        struct  scb *scb, *list_scb;
                    634:        struct  ahc_softc *ahc;
                    635:        int     s;
                    636:        int     found;
                    637:        char    channel;
                    638:
                    639:        scb = (struct scb *)arg;
                    640:        ahc = (struct ahc_softc *)scb->xs->sc_link->adapter_softc;
                    641:
                    642:        s = splbio();
                    643:
                    644: #ifdef AHC_DEBUG
                    645:        printf("%s: SCB %d timed out\n", ahc_name(ahc), scb->hscb->tag);
                    646:        ahc_dump_card_state(ahc);
                    647: #endif
                    648:
                    649:        ahc_pause(ahc);
                    650:
                    651:        if (scb->flags & SCB_ACTIVE) {
                    652:                channel = SCB_GET_CHANNEL(ahc, scb);
                    653:                ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
                    654:                /*
                    655:                 * Go through all of our pending SCBs and remove
                    656:                 * any scheduled timeouts for them. They're about to be
                    657:                 * aborted so no need for them to timeout.
                    658:                 */
                    659:                LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) {
                    660:                        if (list_scb->xs)
                    661:                                timeout_del(&list_scb->xs->stimeout);
                    662:                }
                    663:                found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE);
                    664: #ifdef AHC_DEBUG
                    665:                printf("%s: Issued Channel %c Bus Reset %d SCBs aborted\n",
                    666:                    ahc_name(ahc), channel, found);
                    667: #endif
                    668:        }
                    669:
                    670:        ahc_unpause(ahc);
                    671:        splx(s);
                    672: }
                    673:
                    674:
                    675: void
                    676: ahc_platform_set_tags(struct ahc_softc *ahc,
                    677:                      struct ahc_devinfo *devinfo, int alg)
                    678: {
                    679:        struct ahc_tmode_tstate *tstate;
                    680:
                    681:        ahc_fetch_transinfo(ahc, devinfo->channel, devinfo->our_scsiid,
                    682:                            devinfo->target, &tstate);
                    683:
                    684:        /* XXXX Need to check quirks before doing this! XXXX */
                    685:
                    686:        switch (alg) {
                    687:        case AHC_QUEUE_BASIC:
                    688:        case AHC_QUEUE_TAGGED:
                    689:                tstate->tagenable |= devinfo->target_mask;
                    690:                break;
                    691:        case AHC_QUEUE_NONE:
                    692:                tstate->tagenable &= ~devinfo->target_mask;
                    693:                break;
                    694:        }
                    695: }
                    696:
                    697: int
                    698: ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
                    699: {
                    700:        if (sizeof(struct ahc_platform_data) > 0) {
                    701:                ahc->platform_data = malloc(sizeof(struct ahc_platform_data),
                    702:                    M_DEVBUF, M_NOWAIT);
                    703:                if (ahc->platform_data == NULL)
                    704:                        return (ENOMEM);
                    705:                bzero(ahc->platform_data, sizeof(struct ahc_platform_data));
                    706:        }
                    707:
                    708:        return (0);
                    709: }
                    710:
                    711: void
                    712: ahc_platform_free(struct ahc_softc *ahc)
                    713: {
                    714:        if (sizeof(struct ahc_platform_data) > 0)
                    715:                free(ahc->platform_data, M_DEVBUF);
                    716: }
                    717:
                    718: int
                    719: ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc)
                    720: {
                    721:        return (0);
                    722: }
                    723:
                    724: void
                    725: ahc_send_async(struct ahc_softc *ahc, char channel, u_int target, u_int lun,
                    726:                ac_code code, void *opt_arg)
                    727: {
                    728:        /* Nothing to do here for OpenBSD */
                    729: }
                    730:
                    731: void
                    732: ahc_adapter_req_set_xfer_mode(struct ahc_softc *ahc, struct scb *scb)
                    733: {
                    734:        struct ahc_initiator_tinfo *tinfo;
                    735:        struct ahc_tmode_tstate *tstate;
                    736:        struct ahc_syncrate *syncrate;
                    737:        struct ahc_devinfo devinfo;
                    738:        u_int16_t quirks;
                    739:        u_int width, ppr_options, period, offset;
                    740:        int s;
                    741:
                    742:        s = splbio();
                    743:
                    744:        ahc_scb_devinfo(ahc, &devinfo, scb);
                    745:        quirks = scb->xs->sc_link->quirks;
                    746:        tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
                    747:            devinfo.our_scsiid, devinfo.target, &tstate);
                    748:
                    749:        tstate->discenable |= (ahc->user_discenable & devinfo.target_mask);
                    750:
                    751:        if (quirks & SDEV_NOTAGS)
                    752:                tstate->tagenable &= ~devinfo.target_mask;
                    753:        else if (ahc->user_tagenable & devinfo.target_mask)
                    754:                tstate->tagenable |= devinfo.target_mask;
                    755:
                    756:        if (quirks & SDEV_NOWIDE)
                    757:                width = MSG_EXT_WDTR_BUS_8_BIT;
                    758:        else
                    759:                width = MSG_EXT_WDTR_BUS_16_BIT;
                    760:
                    761:        ahc_validate_width(ahc, NULL, &width, ROLE_UNKNOWN);
                    762:        if (width > tinfo->user.width)
                    763:                width = tinfo->user.width;
                    764:        ahc_set_width(ahc, &devinfo, width, AHC_TRANS_GOAL, FALSE);
                    765:
                    766:        if (quirks & SDEV_NOSYNC) {
                    767:                period = 0;
                    768:                offset = 0;
                    769:        } else {
                    770:                period = tinfo->user.period;
                    771:                offset = tinfo->user.offset;
                    772:        }
                    773:
                    774:        /* XXX Look at saved INQUIRY flags for PPR capabilities XXX */
                    775:        ppr_options = tinfo->user.ppr_options;
                    776:        /* XXX Other reasons to avoid ppr? XXX */
                    777:        if (width < MSG_EXT_WDTR_BUS_16_BIT)
                    778:                ppr_options = 0;
                    779:
                    780:        if ((tstate->discenable & devinfo.target_mask) == 0 ||
                    781:            (tstate->tagenable & devinfo.target_mask) == 0)
                    782:                ppr_options &= ~MSG_EXT_PPR_PROT_IUS;
                    783:
                    784:        syncrate = ahc_find_syncrate(ahc, &period, &ppr_options,
                    785:            AHC_SYNCRATE_MAX);
                    786:        ahc_validate_offset(ahc, NULL, syncrate, &offset, width,
                    787:            ROLE_UNKNOWN);
                    788:
                    789:        if (offset == 0) {
                    790:                period = 0;
                    791:                ppr_options = 0;
                    792:        }
                    793:
                    794:        if (ppr_options != 0 && tinfo->user.transport_version >= 3) {
                    795:                tinfo->goal.transport_version = tinfo->user.transport_version;
                    796:                tinfo->curr.transport_version = tinfo->user.transport_version;
                    797:        }
                    798:
                    799:        ahc_set_syncrate(ahc, &devinfo, syncrate, period, offset, ppr_options,
                    800:            AHC_TRANS_GOAL, FALSE);
                    801:
                    802:        splx(s);
                    803: }

CVSweb