LCOV - code coverage report
Current view: top level - dev/ic - twe.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 508 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 15 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: twe.c,v 1.46 2016/01/22 00:40:25 jsg Exp $    */
       2             : 
       3             : /*
       4             :  * Copyright (c) 2000-2002 Michael Shalayeff.  All rights reserved.
       5             :  *
       6             :  * The SCSI emulation layer is derived from gdt(4) driver,
       7             :  * Copyright (c) 1999, 2000 Niklas Hallqvist. All rights reserved.
       8             :  *
       9             :  * Redistribution and use in source and binary forms, with or without
      10             :  * modification, are permitted provided that the following conditions
      11             :  * are met:
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer.
      14             :  * 2. Redistributions in binary form must reproduce the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer in the
      16             :  *    documentation and/or other materials provided with the distribution.
      17             :  *
      18             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
      19             :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      20             :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      21             :  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
      22             :  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      23             :  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
      24             :  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      25             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
      26             :  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
      27             :  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      28             :  * THE POSSIBILITY OF SUCH DAMAGE.
      29             :  */
      30             : 
      31             : /* #define      TWE_DEBUG */
      32             : 
      33             : #include <sys/param.h>
      34             : #include <sys/systm.h>
      35             : #include <sys/buf.h>
      36             : #include <sys/device.h>
      37             : #include <sys/malloc.h>
      38             : #include <sys/kthread.h>
      39             : 
      40             : #include <machine/bus.h>
      41             : 
      42             : #include <scsi/scsi_all.h>
      43             : #include <scsi/scsi_disk.h>
      44             : #include <scsi/scsiconf.h>
      45             : 
      46             : #include <dev/ic/twereg.h>
      47             : #include <dev/ic/twevar.h>
      48             : 
      49             : #ifdef TWE_DEBUG
      50             : #define TWE_DPRINTF(m,a)        if (twe_debug & (m)) printf a
      51             : #define TWE_D_CMD       0x0001
      52             : #define TWE_D_INTR      0x0002
      53             : #define TWE_D_MISC      0x0004
      54             : #define TWE_D_DMA       0x0008
      55             : #define TWE_D_AEN       0x0010
      56             : int twe_debug = 0;
      57             : #else
      58             : #define TWE_DPRINTF(m,a)        /* m, a */
      59             : #endif
      60             : 
      61             : struct cfdriver twe_cd = {
      62             :         NULL, "twe", DV_DULL
      63             : };
      64             : 
      65             : void    twe_scsi_cmd(struct scsi_xfer *);
      66             : 
      67             : struct scsi_adapter twe_switch = {
      68             :         twe_scsi_cmd, tweminphys, 0, 0,
      69             : };
      70             : 
      71             : void *twe_get_ccb(void *);
      72             : void twe_put_ccb(void *, void *);
      73             : void twe_dispose(struct twe_softc *sc);
      74             : int  twe_cmd(struct twe_ccb *ccb, int flags, int wait);
      75             : int  twe_start(struct twe_ccb *ccb, int wait);
      76             : int  twe_complete(struct twe_ccb *ccb);
      77             : int  twe_done(struct twe_softc *sc, struct twe_ccb *ccb);
      78             : void twe_copy_internal_data(struct scsi_xfer *xs, void *v, size_t size);
      79             : void twe_thread_create(void *v);
      80             : void twe_thread(void *v);
      81             : void twe_aen(void *, void *);
      82             : 
      83             : void *
      84           0 : twe_get_ccb(void *xsc)
      85             : {
      86           0 :         struct twe_softc *sc = xsc;
      87             :         struct twe_ccb *ccb;
      88             : 
      89           0 :         mtx_enter(&sc->sc_ccb_mtx);
      90           0 :         ccb = TAILQ_LAST(&sc->sc_free_ccb, twe_queue_head);
      91           0 :         if (ccb != NULL)
      92           0 :                 TAILQ_REMOVE(&sc->sc_free_ccb, ccb, ccb_link);
      93           0 :         mtx_leave(&sc->sc_ccb_mtx);
      94             : 
      95           0 :         return (ccb);
      96             : }
      97             : 
      98             : void
      99           0 : twe_put_ccb(void *xsc, void *xccb)
     100             : {
     101           0 :         struct twe_softc *sc = xsc;
     102           0 :         struct twe_ccb *ccb = xccb;
     103             : 
     104           0 :         ccb->ccb_state = TWE_CCB_FREE;
     105           0 :         mtx_enter(&sc->sc_ccb_mtx);
     106           0 :         TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
     107           0 :         mtx_leave(&sc->sc_ccb_mtx);
     108           0 : }
     109             : 
     110             : void
     111           0 : twe_dispose(sc)
     112             :         struct twe_softc *sc;
     113             : {
     114             :         register struct twe_ccb *ccb;
     115           0 :         if (sc->sc_cmdmap != NULL) {
     116           0 :                 bus_dmamap_destroy(sc->dmat, sc->sc_cmdmap);
     117             :                 /* traverse the ccbs and destroy the maps */
     118           0 :                 for (ccb = &sc->sc_ccbs[TWE_MAXCMDS - 1]; ccb >= sc->sc_ccbs; ccb--)
     119           0 :                         if (ccb->ccb_dmamap)
     120           0 :                                 bus_dmamap_destroy(sc->dmat, ccb->ccb_dmamap);
     121             :         }
     122           0 :         bus_dmamem_unmap(sc->dmat, sc->sc_cmds, 
     123             :             sizeof(struct twe_cmd) * TWE_MAXCMDS);
     124           0 :         bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1);
     125           0 : }
     126             : 
     127             : int
     128           0 : twe_attach(sc)
     129             :         struct twe_softc *sc;
     130             : {
     131           0 :         struct scsibus_attach_args saa;
     132             :         /* this includes a buffer for drive config req, and a capacity req */
     133           0 :         u_int8_t        param_buf[2 * TWE_SECTOR_SIZE + TWE_ALIGN - 1];
     134           0 :         struct twe_param *pb = (void *)
     135           0 :             (((u_long)param_buf + TWE_ALIGN - 1) & ~(TWE_ALIGN - 1));
     136           0 :         struct twe_param *cap = (void *)((u_int8_t *)pb + TWE_SECTOR_SIZE);
     137             :         struct twe_ccb  *ccb;
     138             :         struct twe_cmd  *cmd;
     139             :         u_int32_t       status;
     140           0 :         int             error, i, retry, nunits, nseg;
     141             :         const char      *errstr;
     142             :         twe_lock_t      lock;
     143             :         paddr_t         pa;
     144             : 
     145           0 :         error = bus_dmamem_alloc(sc->dmat, sizeof(struct twe_cmd) * TWE_MAXCMDS,
     146             :             PAGE_SIZE, 0, sc->sc_cmdseg, 1, &nseg, BUS_DMA_NOWAIT);
     147           0 :         if (error) {
     148           0 :                 printf(": cannot allocate commands (%d)\n", error);
     149           0 :                 return (1);
     150             :         }
     151             : 
     152           0 :         error = bus_dmamem_map(sc->dmat, sc->sc_cmdseg, nseg,
     153             :             sizeof(struct twe_cmd) * TWE_MAXCMDS,
     154             :             (caddr_t *)&sc->sc_cmds, BUS_DMA_NOWAIT);
     155           0 :         if (error) {
     156           0 :                 printf(": cannot map commands (%d)\n", error);
     157           0 :                 bus_dmamem_free(sc->dmat, sc->sc_cmdseg, 1);
     158           0 :                 return (1);
     159             :         }
     160             : 
     161           0 :         error = bus_dmamap_create(sc->dmat,
     162             :             sizeof(struct twe_cmd) * TWE_MAXCMDS, TWE_MAXCMDS,
     163             :             sizeof(struct twe_cmd) * TWE_MAXCMDS, 0,
     164             :             BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_cmdmap);
     165           0 :         if (error) {
     166           0 :                 printf(": cannot create ccb cmd dmamap (%d)\n", error);
     167           0 :                 twe_dispose(sc);
     168           0 :                 return (1);
     169             :         }
     170           0 :         error = bus_dmamap_load(sc->dmat, sc->sc_cmdmap, sc->sc_cmds,
     171             :             sizeof(struct twe_cmd) * TWE_MAXCMDS, NULL, BUS_DMA_NOWAIT);
     172           0 :         if (error) {
     173           0 :                 printf(": cannot load command dma map (%d)\n", error);
     174           0 :                 twe_dispose(sc);
     175           0 :                 return (1);
     176             :         }
     177             : 
     178           0 :         TAILQ_INIT(&sc->sc_ccb2q);
     179           0 :         TAILQ_INIT(&sc->sc_ccbq);
     180           0 :         TAILQ_INIT(&sc->sc_free_ccb);
     181           0 :         TAILQ_INIT(&sc->sc_done_ccb);
     182           0 :         mtx_init(&sc->sc_ccb_mtx, IPL_BIO);
     183           0 :         scsi_iopool_init(&sc->sc_iopool, sc, twe_get_ccb, twe_put_ccb);
     184             : 
     185           0 :         scsi_ioh_set(&sc->sc_aen, &sc->sc_iopool, twe_aen, sc);
     186             : 
     187           0 :         pa = sc->sc_cmdmap->dm_segs[0].ds_addr +
     188             :             sizeof(struct twe_cmd) * (TWE_MAXCMDS - 1);
     189           0 :         for (cmd = (struct twe_cmd *)sc->sc_cmds + TWE_MAXCMDS - 1;
     190           0 :              cmd >= (struct twe_cmd *)sc->sc_cmds; cmd--, pa -= sizeof(*cmd)) {
     191             : 
     192           0 :                 cmd->cmd_index = cmd - (struct twe_cmd *)sc->sc_cmds;
     193           0 :                 ccb = &sc->sc_ccbs[cmd->cmd_index];
     194           0 :                 error = bus_dmamap_create(sc->dmat,
     195             :                     TWE_MAXFER, TWE_MAXOFFSETS, TWE_MAXFER, 0,
     196             :                     BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap);
     197           0 :                 if (error) {
     198           0 :                         printf(": cannot create ccb dmamap (%d)\n", error);
     199           0 :                         twe_dispose(sc);
     200           0 :                         return (1);
     201             :                 }
     202           0 :                 ccb->ccb_sc = sc;
     203           0 :                 ccb->ccb_cmd = cmd;
     204           0 :                 ccb->ccb_cmdpa = pa;
     205           0 :                 ccb->ccb_state = TWE_CCB_FREE;
     206           0 :                 TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, ccb_link);
     207             :         }
     208             : 
     209           0 :         for (errstr = NULL, retry = 3; retry--; ) {
     210             :                 int             veseen_srst;
     211             :                 u_int16_t       aen;
     212             : 
     213             :                 if (errstr)
     214             :                         TWE_DPRINTF(TWE_D_MISC, ("%s ", errstr));
     215             : 
     216           0 :                 for (i = 350000; i--; DELAY(100)) {
     217           0 :                         status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
     218           0 :                         if (status & TWE_STAT_CPURDY)
     219             :                                 break;
     220             :                 }
     221             : 
     222           0 :                 if (!(status & TWE_STAT_CPURDY)) {
     223             :                         errstr = ": card CPU is not ready\n";
     224           0 :                         continue;
     225             :                 }
     226             : 
     227             :                 /* soft reset, disable ints */
     228           0 :                 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
     229             :                     TWE_CTRL_SRST |
     230             :                     TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR |
     231             :                     TWE_CTRL_MCMDI | TWE_CTRL_MRDYI |
     232             :                     TWE_CTRL_MINT);
     233             : 
     234           0 :                 for (i = 350000; i--; DELAY(100)) {
     235           0 :                         status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
     236           0 :                         if (status & TWE_STAT_ATTNI)
     237             :                                 break;
     238             :                 }
     239             : 
     240           0 :                 if (!(status & TWE_STAT_ATTNI)) {
     241             :                         errstr = ": cannot get card's attention\n";
     242           0 :                         continue;
     243             :                 }
     244             : 
     245             :                 /* drain aen queue */
     246           0 :                 for (veseen_srst = 0, aen = -1; aen != TWE_AEN_QEMPTY; ) {
     247             : 
     248           0 :                         ccb = scsi_io_get(&sc->sc_iopool, 0);
     249           0 :                         if (ccb == NULL) {
     250             :                                 errstr = ": out of ccbs\n";
     251           0 :                                 break;
     252             :                         }
     253             : 
     254           0 :                         ccb->ccb_xs = NULL;
     255           0 :                         ccb->ccb_data = pb;
     256           0 :                         ccb->ccb_length = TWE_SECTOR_SIZE;
     257           0 :                         ccb->ccb_state = TWE_CCB_READY;
     258           0 :                         cmd = ccb->ccb_cmd;
     259           0 :                         cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
     260           0 :                         cmd->cmd_op = TWE_CMD_GPARAM;
     261           0 :                         cmd->cmd_param.count = 1;
     262             : 
     263           0 :                         pb->table_id = TWE_PARAM_AEN;
     264           0 :                         pb->param_id = 2;
     265           0 :                         pb->param_size = 2;
     266             : 
     267           0 :                         error = twe_cmd(ccb, BUS_DMA_NOWAIT, 1);
     268           0 :                         scsi_io_put(&sc->sc_iopool, ccb);
     269           0 :                         if (error) {
     270             :                                 errstr = ": error draining attention queue\n";
     271           0 :                                 break;
     272             :                         }
     273             : 
     274           0 :                         aen = *(u_int16_t *)pb->data;
     275             :                         TWE_DPRINTF(TWE_D_AEN, ("aen=%x ", aen));
     276           0 :                         if (aen == TWE_AEN_SRST)
     277           0 :                                 veseen_srst++;
     278             :                 }
     279             : 
     280           0 :                 if (!veseen_srst) {
     281             :                         errstr = ": we don't get it\n";
     282           0 :                         continue;
     283             :                 }
     284             : 
     285           0 :                 if (status & TWE_STAT_CPUERR) {
     286             :                         errstr = ": card CPU error detected\n";
     287           0 :                         continue;
     288             :                 }
     289             : 
     290           0 :                 if (status & TWE_STAT_PCIPAR) {
     291             :                         errstr = ": PCI parity error detected\n";
     292           0 :                         continue;
     293             :                 }
     294             : 
     295           0 :                 if (status & TWE_STAT_QUEUEE ) {
     296             :                         errstr = ": queuing error detected\n";
     297           0 :                         continue;
     298             :                 }
     299             : 
     300           0 :                 if (status & TWE_STAT_PCIABR) {
     301             :                         errstr = ": PCI abort\n";
     302           0 :                         continue;
     303             :                 }
     304             : 
     305           0 :                 while (!(status & TWE_STAT_RQE)) {
     306           0 :                         bus_space_read_4(sc->iot, sc->ioh, TWE_READYQUEUE);
     307           0 :                         status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
     308             :                 }
     309             : 
     310           0 :                 break;
     311             :         }
     312             : 
     313           0 :         if (retry < 0) {
     314           0 :                 printf("%s", errstr);
     315           0 :                 twe_dispose(sc);
     316           0 :                 return 1;
     317             :         }
     318             : 
     319           0 :         ccb = scsi_io_get(&sc->sc_iopool, 0);
     320           0 :         if (ccb == NULL) {
     321           0 :                 printf(": out of ccbs\n");
     322           0 :                 twe_dispose(sc);
     323           0 :                 return 1;
     324             :         }
     325             : 
     326           0 :         ccb->ccb_xs = NULL;
     327           0 :         ccb->ccb_data = pb;
     328           0 :         ccb->ccb_length = TWE_SECTOR_SIZE;
     329           0 :         ccb->ccb_state = TWE_CCB_READY;
     330           0 :         cmd = ccb->ccb_cmd;
     331           0 :         cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
     332           0 :         cmd->cmd_op = TWE_CMD_GPARAM;
     333           0 :         cmd->cmd_param.count = 1;
     334             : 
     335           0 :         pb->table_id = TWE_PARAM_UC;
     336           0 :         pb->param_id = TWE_PARAM_UC;
     337           0 :         pb->param_size = TWE_MAX_UNITS;
     338             : 
     339           0 :         error = twe_cmd(ccb, BUS_DMA_NOWAIT, 1);
     340           0 :         scsi_io_put(&sc->sc_iopool, ccb);
     341           0 :         if (error) {
     342           0 :                 printf(": failed to fetch unit parameters\n");
     343           0 :                 twe_dispose(sc);
     344           0 :                 return 1;
     345             :         }
     346             : 
     347             :         /* we are assuming last read status was good */
     348           0 :         printf(": Escalade V%d.%d\n", TWE_MAJV(status), TWE_MINV(status));
     349             : 
     350           0 :         for (nunits = i = 0; i < TWE_MAX_UNITS; i++) {
     351           0 :                 if (pb->data[i] == 0)
     352             :                         continue;
     353             : 
     354           0 :                 ccb = scsi_io_get(&sc->sc_iopool, 0);
     355           0 :                 if (ccb == NULL) {
     356           0 :                         printf(": out of ccbs\n");
     357           0 :                         twe_dispose(sc);
     358           0 :                         return 1;
     359             :                 }
     360             : 
     361           0 :                 ccb->ccb_xs = NULL;
     362           0 :                 ccb->ccb_data = cap;
     363           0 :                 ccb->ccb_length = TWE_SECTOR_SIZE;
     364           0 :                 ccb->ccb_state = TWE_CCB_READY;
     365           0 :                 cmd = ccb->ccb_cmd;
     366           0 :                 cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
     367           0 :                 cmd->cmd_op = TWE_CMD_GPARAM;
     368           0 :                 cmd->cmd_param.count = 1;
     369             : 
     370           0 :                 cap->table_id = TWE_PARAM_UI + i;
     371           0 :                 cap->param_id = 4;
     372           0 :                 cap->param_size = 4; /* 4 bytes */
     373             : 
     374           0 :                 lock = TWE_LOCK(sc);
     375           0 :                 twe_cmd(ccb, BUS_DMA_NOWAIT, 1);
     376           0 :                 TWE_UNLOCK(sc, lock);
     377           0 :                 scsi_io_put(&sc->sc_iopool, ccb);
     378           0 :                 if (error) {
     379           0 :                         printf("%s: error fetching capacity for unit %d\n",
     380           0 :                             sc->sc_dev.dv_xname, i);
     381           0 :                         continue;
     382             :                 }
     383             : 
     384           0 :                 nunits++;
     385           0 :                 sc->sc_hdr[i].hd_present = 1;
     386           0 :                 sc->sc_hdr[i].hd_devtype = 0;
     387           0 :                 sc->sc_hdr[i].hd_size = letoh32(*(u_int32_t *)cap->data);
     388             :                 TWE_DPRINTF(TWE_D_MISC, ("twed%d: size=%d\n",
     389             :                     i, sc->sc_hdr[i].hd_size));
     390           0 :         }
     391             : 
     392           0 :         if (!nunits)
     393           0 :                 nunits++;
     394             : 
     395             :         /* TODO: fetch & print cache params? */
     396             : 
     397           0 :         sc->sc_link.adapter_softc = sc;
     398           0 :         sc->sc_link.adapter = &twe_switch;
     399           0 :         sc->sc_link.adapter_target = TWE_MAX_UNITS;
     400           0 :         sc->sc_link.openings = TWE_MAXCMDS / nunits;
     401           0 :         sc->sc_link.adapter_buswidth = TWE_MAX_UNITS;
     402           0 :         sc->sc_link.pool = &sc->sc_iopool;
     403             : 
     404           0 :         bzero(&saa, sizeof(saa));
     405           0 :         saa.saa_sc_link = &sc->sc_link;
     406             : 
     407           0 :         config_found(&sc->sc_dev, &saa, scsiprint);
     408             : 
     409           0 :         kthread_create_deferred(twe_thread_create, sc);
     410             : 
     411           0 :         return (0);
     412           0 : }
     413             : 
     414             : void
     415           0 : twe_thread_create(void *v)
     416             : {
     417           0 :         struct twe_softc *sc = v;
     418             : 
     419           0 :         if (kthread_create(twe_thread, sc, &sc->sc_thread,
     420           0 :             sc->sc_dev.dv_xname)) {
     421             :                 /* TODO disable twe */
     422           0 :                 printf("%s: failed to create kernel thread, disabled\n",
     423             :                     sc->sc_dev.dv_xname);
     424           0 :                 return;
     425             :         }
     426             : 
     427             :         TWE_DPRINTF(TWE_D_CMD, ("stat=%b ",
     428             :             bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));
     429             :         /*
     430             :          * ack all before enable, cannot be done in one
     431             :          * operation as it seems clear is not processed
     432             :          * if enable is specified.
     433             :          */
     434           0 :         bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
     435             :             TWE_CTRL_CHOSTI | TWE_CTRL_CATTNI | TWE_CTRL_CERR);
     436             :         TWE_DPRINTF(TWE_D_CMD, ("stat=%b ",
     437             :             bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS), TWE_STAT_BITS));
     438             :         /* enable interrupts */
     439           0 :         bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
     440             :             TWE_CTRL_EINT | TWE_CTRL_ERDYI |
     441             :             /*TWE_CTRL_HOSTI |*/ TWE_CTRL_MCMDI);
     442           0 : }
     443             : 
     444             : void
     445           0 : twe_thread(v)
     446             :         void *v;
     447             : {
     448           0 :         struct twe_softc *sc = v;
     449             :         struct twe_ccb *ccb;
     450             :         twe_lock_t lock;
     451             :         u_int32_t status;
     452             :         int err;
     453             : 
     454           0 :         for (;;) {
     455           0 :                 lock = TWE_LOCK(sc);
     456             : 
     457           0 :                 while (!TAILQ_EMPTY(&sc->sc_done_ccb)) {
     458             :                         ccb = TAILQ_FIRST(&sc->sc_done_ccb);
     459           0 :                         TAILQ_REMOVE(&sc->sc_done_ccb, ccb, ccb_link);
     460           0 :                         if ((err = twe_done(sc, ccb)))
     461           0 :                                 printf("%s: done failed (%d)\n",
     462           0 :                                     sc->sc_dev.dv_xname, err);
     463             :                 }
     464             : 
     465           0 :                 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
     466             :                 TWE_DPRINTF(TWE_D_INTR, ("twe_thread stat=%b ",
     467             :                     status & TWE_STAT_FLAGS, TWE_STAT_BITS));
     468           0 :                 while (!(status & TWE_STAT_CQF) &&
     469           0 :                     !TAILQ_EMPTY(&sc->sc_ccb2q)) {
     470             : 
     471           0 :                         ccb = TAILQ_LAST(&sc->sc_ccb2q, twe_queue_head);
     472           0 :                         TAILQ_REMOVE(&sc->sc_ccb2q, ccb, ccb_link);
     473             : 
     474           0 :                         ccb->ccb_state = TWE_CCB_QUEUED;
     475           0 :                         TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
     476           0 :                         bus_space_write_4(sc->iot, sc->ioh, TWE_COMMANDQUEUE,
     477             :                             ccb->ccb_cmdpa);
     478             : 
     479           0 :                         status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
     480             :                         TWE_DPRINTF(TWE_D_INTR, ("twe_thread stat=%b ",
     481             :                             status & TWE_STAT_FLAGS, TWE_STAT_BITS));
     482             :                 }
     483             : 
     484           0 :                 if (!TAILQ_EMPTY(&sc->sc_ccb2q))
     485           0 :                         bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
     486             :                             TWE_CTRL_ECMDI);
     487             : 
     488           0 :                 TWE_UNLOCK(sc, lock);
     489           0 :                 sc->sc_thread_on = 1;
     490           0 :                 tsleep(sc, PWAIT, "twespank", 0);
     491             :         }
     492             : }
     493             : 
     494             : int
     495           0 : twe_cmd(ccb, flags, wait)
     496             :         struct twe_ccb *ccb;
     497             :         int flags, wait;
     498             : {
     499           0 :         struct twe_softc *sc = ccb->ccb_sc;
     500             :         bus_dmamap_t dmap;
     501             :         struct twe_cmd *cmd;
     502             :         struct twe_segs *sgp;
     503             :         int error, i;
     504             : 
     505           0 :         if (ccb->ccb_data && ((u_long)ccb->ccb_data & (TWE_ALIGN - 1))) {
     506             :                 TWE_DPRINTF(TWE_D_DMA, ("data=%p is unaligned ",ccb->ccb_data));
     507           0 :                 ccb->ccb_realdata = ccb->ccb_data;
     508             : 
     509           0 :                 error = bus_dmamem_alloc(sc->dmat, ccb->ccb_length, PAGE_SIZE,
     510             :                     0, ccb->ccb_2bseg, TWE_MAXOFFSETS, &ccb->ccb_2nseg,
     511             :                     BUS_DMA_NOWAIT);
     512           0 :                 if (error) {
     513             :                         TWE_DPRINTF(TWE_D_DMA, ("2buf alloc failed(%d) ", error));
     514           0 :                         return (ENOMEM);
     515             :                 }
     516             : 
     517           0 :                 error = bus_dmamem_map(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg,
     518             :                     ccb->ccb_length, (caddr_t *)&ccb->ccb_data, BUS_DMA_NOWAIT);
     519           0 :                 if (error) {
     520             :                         TWE_DPRINTF(TWE_D_DMA, ("2buf map failed(%d) ", error));
     521           0 :                         bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg);
     522           0 :                         return (ENOMEM);
     523             :                 }
     524           0 :                 bcopy(ccb->ccb_realdata, ccb->ccb_data, ccb->ccb_length);
     525           0 :         } else
     526           0 :                 ccb->ccb_realdata = NULL;
     527             : 
     528           0 :         dmap = ccb->ccb_dmamap;
     529           0 :         cmd = ccb->ccb_cmd;
     530           0 :         cmd->cmd_status = 0;
     531             : 
     532           0 :         if (ccb->ccb_data) {
     533           0 :                 error = bus_dmamap_load(sc->dmat, dmap, ccb->ccb_data,
     534             :                     ccb->ccb_length, NULL, flags);
     535           0 :                 if (error) {
     536           0 :                         if (error == EFBIG)
     537           0 :                                 printf("more than %d dma segs\n", TWE_MAXOFFSETS);
     538             :                         else
     539           0 :                                 printf("error %d loading dma map\n", error);
     540             : 
     541           0 :                         if (ccb->ccb_realdata) {
     542           0 :                                 bus_dmamem_unmap(sc->dmat, ccb->ccb_data,
     543             :                                     ccb->ccb_length);
     544           0 :                                 bus_dmamem_free(sc->dmat, ccb->ccb_2bseg,
     545             :                                     ccb->ccb_2nseg);
     546           0 :                         }
     547           0 :                         return error;
     548             :                 }
     549             :                 /* load addresses into command */
     550           0 :                 switch (cmd->cmd_op) {
     551             :                 case TWE_CMD_GPARAM:
     552             :                 case TWE_CMD_SPARAM:
     553           0 :                         sgp = cmd->cmd_param.segs;
     554           0 :                         break;
     555             :                 case TWE_CMD_READ:
     556             :                 case TWE_CMD_WRITE:
     557           0 :                         sgp = cmd->cmd_io.segs;
     558           0 :                         break;
     559             :                 default:
     560             :                         /* no data transfer */
     561             :                         TWE_DPRINTF(TWE_D_DMA, ("twe_cmd: unknown sgp op=%x\n",
     562             :                             cmd->cmd_op));
     563             :                         sgp = NULL;
     564           0 :                         break;
     565             :                 }
     566             :                 TWE_DPRINTF(TWE_D_DMA, ("data=%p<", ccb->ccb_data));
     567           0 :                 if (sgp) {
     568             :                         /*
     569             :                          * we know that size is in the upper byte,
     570             :                          * and we do not worry about overflow
     571             :                          */
     572           0 :                         cmd->cmd_op += (2 * dmap->dm_nsegs) << 8;
     573           0 :                         bzero (sgp, TWE_MAXOFFSETS * sizeof(*sgp));
     574           0 :                         for (i = 0; i < dmap->dm_nsegs; i++, sgp++) {
     575           0 :                                 sgp->twes_addr = htole32(dmap->dm_segs[i].ds_addr);
     576           0 :                                 sgp->twes_len  = htole32(dmap->dm_segs[i].ds_len);
     577             :                                 TWE_DPRINTF(TWE_D_DMA, ("%x[%x] ",
     578             :                                     dmap->dm_segs[i].ds_addr,
     579             :                                     dmap->dm_segs[i].ds_len));
     580             :                         }
     581             :                 }
     582             :                 TWE_DPRINTF(TWE_D_DMA, ("> "));
     583           0 :                 bus_dmamap_sync(sc->dmat, dmap, 0, dmap->dm_mapsize,
     584             :                     BUS_DMASYNC_PREWRITE);
     585           0 :         }
     586           0 :         bus_dmamap_sync(sc->dmat, sc->sc_cmdmap, 0, sc->sc_cmdmap->dm_mapsize,
     587             :             BUS_DMASYNC_PREWRITE);
     588             : 
     589           0 :         if ((error = twe_start(ccb, wait))) {
     590           0 :                 bus_dmamap_unload(sc->dmat, dmap);
     591           0 :                 if (ccb->ccb_realdata) {
     592           0 :                         bus_dmamem_unmap(sc->dmat, ccb->ccb_data,
     593             :                             ccb->ccb_length);
     594           0 :                         bus_dmamem_free(sc->dmat, ccb->ccb_2bseg,
     595             :                             ccb->ccb_2nseg);
     596           0 :                 }
     597           0 :                 return (error);
     598             :         }
     599             : 
     600           0 :         return wait? twe_complete(ccb) : 0;
     601           0 : }
     602             : 
     603             : int
     604           0 : twe_start(ccb, wait)
     605             :         struct twe_ccb *ccb;
     606             :         int wait;
     607             : {
     608           0 :         struct twe_softc*sc = ccb->ccb_sc;
     609           0 :         struct twe_cmd  *cmd = ccb->ccb_cmd;
     610             :         u_int32_t       status;
     611             :         int i;
     612             : 
     613           0 :         cmd->cmd_op = htole16(cmd->cmd_op);
     614             : 
     615           0 :         if (!wait) {
     616             : 
     617             :                 TWE_DPRINTF(TWE_D_CMD, ("prequeue(%d) ", cmd->cmd_index));
     618           0 :                 ccb->ccb_state = TWE_CCB_PREQUEUED;
     619           0 :                 TAILQ_INSERT_TAIL(&sc->sc_ccb2q, ccb, ccb_link);
     620           0 :                 wakeup(sc);
     621           0 :                 return 0;
     622             :         }
     623             : 
     624           0 :         for (i = 1000; i--; DELAY(10)) {
     625             : 
     626           0 :                 status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
     627           0 :                 if (!(status & TWE_STAT_CQF))
     628             :                         break;
     629             :                 TWE_DPRINTF(TWE_D_CMD,  ("twe_start stat=%b ",
     630             :                     status & TWE_STAT_FLAGS, TWE_STAT_BITS));
     631             :         }
     632             : 
     633           0 :         if (!(status & TWE_STAT_CQF)) {
     634           0 :                 bus_space_write_4(sc->iot, sc->ioh, TWE_COMMANDQUEUE,
     635             :                     ccb->ccb_cmdpa);
     636             : 
     637             :                 TWE_DPRINTF(TWE_D_CMD, ("queue(%d) ", cmd->cmd_index));
     638           0 :                 ccb->ccb_state = TWE_CCB_QUEUED;
     639           0 :                 TAILQ_INSERT_TAIL(&sc->sc_ccbq, ccb, ccb_link);
     640           0 :                 return 0;
     641             : 
     642             :         } else {
     643             : 
     644           0 :                 printf("%s: twe_start(%d) timed out\n",
     645           0 :                     sc->sc_dev.dv_xname, cmd->cmd_index);
     646             : 
     647           0 :                 return EPERM;
     648             :         }
     649           0 : }
     650             : 
     651             : int
     652           0 : twe_complete(ccb)
     653             :         struct twe_ccb *ccb;
     654             : {
     655           0 :         struct twe_softc *sc = ccb->ccb_sc;
     656           0 :         struct scsi_xfer *xs = ccb->ccb_xs;
     657             :         int i;
     658             : 
     659           0 :         for (i = 100 * (xs? xs->timeout : 35000); i--; DELAY(10)) {
     660           0 :                 u_int32_t status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
     661             : 
     662             :                 /* TWE_DPRINTF(TWE_D_CMD,  ("twe_intr stat=%b ",
     663             :                     status & TWE_STAT_FLAGS, TWE_STAT_BITS)); */
     664             : 
     665           0 :                 while (!(status & TWE_STAT_RQE)) {
     666             :                         struct twe_ccb *ccb1;
     667             :                         u_int32_t ready;
     668             : 
     669           0 :                         ready = bus_space_read_4(sc->iot, sc->ioh,
     670             :                             TWE_READYQUEUE);
     671             : 
     672             :                         TWE_DPRINTF(TWE_D_CMD, ("ready=%x ", ready));
     673             : 
     674           0 :                         ccb1 = &sc->sc_ccbs[TWE_READYID(ready)];
     675           0 :                         TAILQ_REMOVE(&sc->sc_ccbq, ccb1, ccb_link);
     676           0 :                         ccb1->ccb_state = TWE_CCB_DONE;
     677           0 :                         if (!twe_done(sc, ccb1) && ccb1 == ccb) {
     678             :                                 TWE_DPRINTF(TWE_D_CMD, ("complete\n"));
     679           0 :                                 return 0;
     680             :                         }
     681             : 
     682           0 :                         status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
     683             :                         /* TWE_DPRINTF(TWE_D_CMD,  ("twe_intr stat=%b ",
     684             :                             status & TWE_STAT_FLAGS, TWE_STAT_BITS)); */
     685           0 :                 }
     686           0 :         }
     687             : 
     688           0 :         return 1;
     689           0 : }
     690             : 
     691             : int
     692           0 : twe_done(sc, ccb)
     693             :         struct twe_softc *sc;
     694             :         struct twe_ccb *ccb;
     695             : {
     696           0 :         struct twe_cmd *cmd = ccb->ccb_cmd;
     697           0 :         struct scsi_xfer *xs = ccb->ccb_xs;
     698             :         bus_dmamap_t    dmap;
     699             :         twe_lock_t      lock;
     700             : 
     701             :         TWE_DPRINTF(TWE_D_CMD, ("done(%d) ", cmd->cmd_index));
     702             : 
     703           0 :         if (ccb->ccb_state != TWE_CCB_DONE) {
     704           0 :                 printf("%s: undone ccb %d ready\n",
     705           0 :                      sc->sc_dev.dv_xname, cmd->cmd_index);
     706           0 :                 return 1;
     707             :         }
     708             : 
     709           0 :         dmap = ccb->ccb_dmamap;
     710           0 :         if (xs) {
     711           0 :                 if (xs->cmd->opcode != PREVENT_ALLOW &&
     712           0 :                     xs->cmd->opcode != SYNCHRONIZE_CACHE) {
     713           0 :                         bus_dmamap_sync(sc->dmat, dmap, 0,
     714             :                             dmap->dm_mapsize, (xs->flags & SCSI_DATA_IN) ?
     715             :                             BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
     716           0 :                         bus_dmamap_unload(sc->dmat, dmap);
     717           0 :                 }
     718             :         } else {
     719           0 :                 switch (letoh16(cmd->cmd_op)) {
     720             :                 case TWE_CMD_GPARAM:
     721             :                 case TWE_CMD_READ:
     722           0 :                         bus_dmamap_sync(sc->dmat, dmap, 0,
     723             :                             dmap->dm_mapsize, BUS_DMASYNC_POSTREAD);
     724           0 :                         bus_dmamap_unload(sc->dmat, dmap);
     725           0 :                         break;
     726             :                 case TWE_CMD_SPARAM:
     727             :                 case TWE_CMD_WRITE:
     728           0 :                         bus_dmamap_sync(sc->dmat, dmap, 0,
     729             :                             dmap->dm_mapsize, BUS_DMASYNC_POSTWRITE);
     730           0 :                         bus_dmamap_unload(sc->dmat, dmap);
     731           0 :                         break;
     732             :                 default:
     733             :                         /* no data */
     734             :                         break;
     735             :                 }
     736             :         }
     737             : 
     738           0 :         if (ccb->ccb_realdata) {
     739           0 :                 bcopy(ccb->ccb_data, ccb->ccb_realdata, ccb->ccb_length);
     740           0 :                 bus_dmamem_unmap(sc->dmat, ccb->ccb_data, ccb->ccb_length);
     741           0 :                 bus_dmamem_free(sc->dmat, ccb->ccb_2bseg, ccb->ccb_2nseg);
     742           0 :         }
     743             : 
     744           0 :         lock = TWE_LOCK(sc);
     745             : 
     746           0 :         if (xs) {
     747           0 :                 xs->resid = 0;
     748           0 :                 scsi_done(xs);
     749           0 :         }
     750           0 :         TWE_UNLOCK(sc, lock);
     751             : 
     752           0 :         return 0;
     753           0 : }
     754             : 
     755             : void
     756           0 : tweminphys(struct buf *bp, struct scsi_link *sl)
     757             : {
     758           0 :         if (bp->b_bcount > TWE_MAXFER)
     759           0 :                 bp->b_bcount = TWE_MAXFER;
     760           0 :         minphys(bp);
     761           0 : }
     762             : 
     763             : void
     764           0 : twe_copy_internal_data(xs, v, size)
     765             :         struct scsi_xfer *xs;
     766             :         void *v;
     767             :         size_t size;
     768             : {
     769             :         size_t copy_cnt;
     770             : 
     771             :         TWE_DPRINTF(TWE_D_MISC, ("twe_copy_internal_data "));
     772             : 
     773           0 :         if (!xs->datalen)
     774           0 :                 printf("uio move is not yet supported\n");
     775             :         else {
     776           0 :                 copy_cnt = MIN(size, xs->datalen);
     777           0 :                 bcopy(v, xs->data, copy_cnt);
     778             :         }
     779           0 : }
     780             : 
     781             : void
     782           0 : twe_scsi_cmd(xs)
     783             :         struct scsi_xfer *xs;
     784             : {
     785           0 :         struct scsi_link *link = xs->sc_link;
     786           0 :         struct twe_softc *sc = link->adapter_softc;
     787           0 :         struct twe_ccb *ccb = xs->io;
     788             :         struct twe_cmd *cmd;
     789           0 :         struct scsi_inquiry_data inq;
     790           0 :         struct scsi_sense_data sd;
     791           0 :         struct scsi_read_cap_data rcd;
     792           0 :         u_int8_t target = link->target;
     793             :         u_int32_t blockno, blockcnt;
     794             :         struct scsi_rw *rw;
     795             :         struct scsi_rw_big *rwb;
     796             :         int error, op, flags, wait;
     797             :         twe_lock_t lock;
     798             : 
     799             : 
     800           0 :         if (target >= TWE_MAX_UNITS || !sc->sc_hdr[target].hd_present ||
     801           0 :             link->lun != 0) {
     802           0 :                 xs->error = XS_DRIVER_STUFFUP;
     803           0 :                 scsi_done(xs);
     804           0 :                 return;
     805             :         }
     806             : 
     807             :         TWE_DPRINTF(TWE_D_CMD, ("twe_scsi_cmd "));
     808             : 
     809           0 :         xs->error = XS_NOERROR;
     810             : 
     811           0 :         switch (xs->cmd->opcode) {
     812             :         case TEST_UNIT_READY:
     813             :         case START_STOP:
     814             : #if 0
     815             :         case VERIFY:
     816             : #endif
     817             :                 TWE_DPRINTF(TWE_D_CMD, ("opc %d tgt %d ", xs->cmd->opcode,
     818             :                     target));
     819             :                 break;
     820             : 
     821             :         case REQUEST_SENSE:
     822             :                 TWE_DPRINTF(TWE_D_CMD, ("REQUEST SENSE tgt %d ", target));
     823           0 :                 bzero(&sd, sizeof sd);
     824           0 :                 sd.error_code = SSD_ERRCODE_CURRENT;
     825           0 :                 sd.segment = 0;
     826           0 :                 sd.flags = SKEY_NO_SENSE;
     827           0 :                 *(u_int32_t*)sd.info = htole32(0);
     828           0 :                 sd.extra_len = 0;
     829           0 :                 twe_copy_internal_data(xs, &sd, sizeof sd);
     830           0 :                 break;
     831             : 
     832             :         case INQUIRY:
     833             :                 TWE_DPRINTF(TWE_D_CMD, ("INQUIRY tgt %d devtype %x ", target,
     834             :                     sc->sc_hdr[target].hd_devtype));
     835           0 :                 bzero(&inq, sizeof inq);
     836           0 :                 inq.device =
     837           0 :                     (sc->sc_hdr[target].hd_devtype & 4) ? T_CDROM : T_DIRECT;
     838           0 :                 inq.dev_qual2 =
     839           0 :                     (sc->sc_hdr[target].hd_devtype & 1) ? SID_REMOVABLE : 0;
     840           0 :                 inq.version = 2;
     841           0 :                 inq.response_format = 2;
     842           0 :                 inq.additional_length = 32;
     843           0 :                 strlcpy(inq.vendor, "3WARE  ", sizeof inq.vendor);
     844           0 :                 snprintf(inq.product, sizeof inq.product, "Host drive  #%02d",
     845             :                     target);
     846           0 :                 strlcpy(inq.revision, "   ", sizeof inq.revision);
     847           0 :                 twe_copy_internal_data(xs, &inq, sizeof inq);
     848           0 :                 break;
     849             : 
     850             :         case READ_CAPACITY:
     851             :                 TWE_DPRINTF(TWE_D_CMD, ("READ CAPACITY tgt %d ", target));
     852           0 :                 bzero(&rcd, sizeof rcd);
     853           0 :                 _lto4b(sc->sc_hdr[target].hd_size - 1, rcd.addr);
     854           0 :                 _lto4b(TWE_SECTOR_SIZE, rcd.length);
     855           0 :                 twe_copy_internal_data(xs, &rcd, sizeof rcd);
     856           0 :                 break;
     857             : 
     858             :         case PREVENT_ALLOW:
     859             :                 TWE_DPRINTF(TWE_D_CMD, ("PREVENT/ALLOW "));
     860           0 :                 scsi_done(xs);
     861           0 :                 return;
     862             : 
     863             :         case READ_COMMAND:
     864             :         case READ_BIG:
     865             :         case WRITE_COMMAND:
     866             :         case WRITE_BIG:
     867             :         case SYNCHRONIZE_CACHE:
     868           0 :                 lock = TWE_LOCK(sc);
     869             : 
     870             :                 flags = 0;
     871           0 :                 if (xs->cmd->opcode == SYNCHRONIZE_CACHE) {
     872             :                         blockno = blockcnt = 0;
     873           0 :                 } else {
     874             :                         /* A read or write operation. */
     875           0 :                         if (xs->cmdlen == 6) {
     876           0 :                                 rw = (struct scsi_rw *)xs->cmd;
     877           0 :                                 blockno = _3btol(rw->addr) &
     878             :                                     (SRW_TOPADDR << 16 | 0xffff);
     879           0 :                                 blockcnt = rw->length ? rw->length : 0x100;
     880           0 :                         } else {
     881           0 :                                 rwb = (struct scsi_rw_big *)xs->cmd;
     882           0 :                                 blockno = _4btol(rwb->addr);
     883           0 :                                 blockcnt = _2btol(rwb->length);
     884             :                                 /* reflect DPO & FUA flags */
     885           0 :                                 if (xs->cmd->opcode == WRITE_BIG &&
     886           0 :                                     rwb->byte2 & 0x18)
     887           0 :                                         flags = TWE_FLAGS_CACHEDISABLE;
     888             :                         }
     889           0 :                         if (blockno >= sc->sc_hdr[target].hd_size ||
     890           0 :                             blockno + blockcnt > sc->sc_hdr[target].hd_size) {
     891           0 :                                 printf("%s: out of bounds %u-%u >= %u\n",
     892           0 :                                     sc->sc_dev.dv_xname, blockno, blockcnt,
     893           0 :                                     sc->sc_hdr[target].hd_size);
     894           0 :                                 xs->error = XS_DRIVER_STUFFUP;
     895           0 :                                 scsi_done(xs);
     896           0 :                                 TWE_UNLOCK(sc, lock);
     897           0 :                                 return;
     898             :                         }
     899             :                 }
     900             : 
     901           0 :                 switch (xs->cmd->opcode) {
     902           0 :                 case READ_COMMAND:      op = TWE_CMD_READ;      break;
     903           0 :                 case READ_BIG:          op = TWE_CMD_READ;      break;
     904           0 :                 case WRITE_COMMAND:     op = TWE_CMD_WRITE;     break;
     905           0 :                 case WRITE_BIG:         op = TWE_CMD_WRITE;     break;
     906           0 :                 default:                op = TWE_CMD_NOP;       break;
     907             :                 }
     908             : 
     909           0 :                 ccb->ccb_xs = xs;
     910           0 :                 ccb->ccb_data = xs->data;
     911           0 :                 ccb->ccb_length = xs->datalen;
     912           0 :                 ccb->ccb_state = TWE_CCB_READY;
     913           0 :                 cmd = ccb->ccb_cmd;
     914           0 :                 cmd->cmd_unit_host = TWE_UNITHOST(target, 0); /* XXX why 0? */
     915           0 :                 cmd->cmd_op = op;
     916           0 :                 cmd->cmd_flags = flags;
     917           0 :                 cmd->cmd_io.count = htole16(blockcnt);
     918           0 :                 cmd->cmd_io.lba = htole32(blockno);
     919           0 :                 wait = xs->flags & SCSI_POLL;
     920           0 :                 if (!sc->sc_thread_on)
     921           0 :                         wait |= SCSI_POLL;
     922             : 
     923           0 :                 if ((error = twe_cmd(ccb, ((xs->flags & SCSI_NOSLEEP)?
     924             :                     BUS_DMA_NOWAIT : BUS_DMA_WAITOK), wait))) {
     925             : 
     926             :                         TWE_DPRINTF(TWE_D_CMD, ("failed %p ", xs));
     927           0 :                         xs->error = XS_DRIVER_STUFFUP;
     928           0 :                         scsi_done(xs);
     929           0 :                 }
     930             : 
     931           0 :                 TWE_UNLOCK(sc, lock);
     932           0 :                 return;
     933             : 
     934             :         default:
     935             :                 TWE_DPRINTF(TWE_D_CMD, ("unsupported scsi command %#x tgt %d ",
     936             :                     xs->cmd->opcode, target));
     937           0 :                 xs->error = XS_DRIVER_STUFFUP;
     938           0 :         }
     939             : 
     940           0 :         scsi_done(xs);
     941           0 : }
     942             : 
     943             : int
     944           0 : twe_intr(v)
     945             :         void *v;
     946             : {
     947           0 :         struct twe_softc *sc = v;
     948             :         struct twe_ccb  *ccb;
     949             :         u_int32_t       status;
     950             :         int             rv = 0;
     951             : 
     952           0 :         status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
     953             :         TWE_DPRINTF(TWE_D_INTR,  ("twe_intr stat=%b ",
     954             :             status & TWE_STAT_FLAGS, TWE_STAT_BITS));
     955             : #if 0
     956             :         if (status & TWE_STAT_HOSTI) {
     957             : 
     958             :                 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
     959             :                     TWE_CTRL_CHOSTI);
     960             :         }
     961             : #endif
     962             : 
     963           0 :         if (status & TWE_STAT_RDYI) {
     964             : 
     965           0 :                 while (!(status & TWE_STAT_RQE)) {
     966             : 
     967             :                         u_int32_t ready;
     968             : 
     969             :                         /*
     970             :                          * it seems that reading ready queue
     971             :                          * we get all the status bits in each ready word.
     972             :                          * i wonder if it's legal to use those for
     973             :                          * status and avoid extra read below
     974             :                          */
     975           0 :                         ready = bus_space_read_4(sc->iot, sc->ioh,
     976             :                             TWE_READYQUEUE);
     977             : 
     978           0 :                         ccb = &sc->sc_ccbs[TWE_READYID(ready)];
     979           0 :                         TAILQ_REMOVE(&sc->sc_ccbq, ccb, ccb_link);
     980           0 :                         ccb->ccb_state = TWE_CCB_DONE;
     981           0 :                         TAILQ_INSERT_TAIL(&sc->sc_done_ccb, ccb, ccb_link);
     982           0 :                         rv++;
     983             : 
     984           0 :                         status = bus_space_read_4(sc->iot, sc->ioh, TWE_STATUS);
     985             :                         TWE_DPRINTF(TWE_D_INTR, ("twe_intr stat=%b ",
     986             :                             status & TWE_STAT_FLAGS, TWE_STAT_BITS));
     987             :                 }
     988             :         }
     989             : 
     990           0 :         if (status & TWE_STAT_CMDI) {
     991           0 :                 rv++;
     992           0 :                 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
     993             :                     TWE_CTRL_MCMDI);
     994           0 :         }
     995             : 
     996           0 :         if (rv)
     997           0 :                 wakeup(sc);
     998             : 
     999           0 :         if (status & TWE_STAT_ATTNI) {
    1000             :                 /*
    1001             :                  * we know no attentions of interest right now.
    1002             :                  * one of those would be mirror degradation i think.
    1003             :                  * or, what else exists in there?
    1004             :                  * maybe 3ware can answer that?
    1005             :                  */
    1006           0 :                 bus_space_write_4(sc->iot, sc->ioh, TWE_CONTROL,
    1007             :                     TWE_CTRL_CATTNI);
    1008             : 
    1009           0 :                 scsi_ioh_add(&sc->sc_aen);
    1010           0 :         }
    1011             : 
    1012           0 :         return rv;
    1013             : }
    1014             : 
    1015             : void
    1016           0 : twe_aen(void *cookie, void *io)
    1017             : {
    1018           0 :         struct twe_softc *sc = cookie;
    1019           0 :         struct twe_ccb *ccb = io;
    1020           0 :         struct twe_cmd *cmd = ccb->ccb_cmd;
    1021             : 
    1022           0 :         u_int8_t param_buf[2 * TWE_SECTOR_SIZE + TWE_ALIGN - 1];
    1023           0 :         struct twe_param *pb = (void *) (((u_long)param_buf +
    1024           0 :             TWE_ALIGN - 1) & ~(TWE_ALIGN - 1));
    1025             :         u_int16_t aen;
    1026             : 
    1027             :         twe_lock_t lock;
    1028             :         int error;
    1029             : 
    1030           0 :         ccb->ccb_xs = NULL;
    1031           0 :         ccb->ccb_data = pb;
    1032           0 :         ccb->ccb_length = TWE_SECTOR_SIZE;
    1033           0 :         ccb->ccb_state = TWE_CCB_READY;
    1034           0 :         cmd->cmd_unit_host = TWE_UNITHOST(0, 0);
    1035           0 :         cmd->cmd_op = TWE_CMD_GPARAM;
    1036           0 :         cmd->cmd_flags = 0;
    1037           0 :         cmd->cmd_param.count = 1;
    1038             : 
    1039           0 :         pb->table_id = TWE_PARAM_AEN;
    1040           0 :         pb->param_id = 2;
    1041           0 :         pb->param_size = 2;
    1042             : 
    1043           0 :         lock = TWE_LOCK(sc);
    1044           0 :         error = twe_cmd(ccb, BUS_DMA_NOWAIT, 1);
    1045           0 :         TWE_UNLOCK(sc, lock);
    1046           0 :         scsi_io_put(&sc->sc_iopool, ccb);
    1047             : 
    1048           0 :         if (error) {
    1049           0 :                 printf("%s: error draining attention queue\n",
    1050           0 :                     sc->sc_dev.dv_xname);
    1051           0 :                 return;
    1052             :         }
    1053             : 
    1054           0 :         aen = *(u_int16_t *)pb->data;
    1055           0 :         if (aen != TWE_AEN_QEMPTY) 
    1056           0 :                 scsi_ioh_add(&sc->sc_aen);
    1057           0 : }

Generated by: LCOV version 1.13