root/dev/isa/wds.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. wds_wait
  2. wds_cmd
  3. wdsprobe
  4. wdsprint
  5. wdsattach
  6. wds_finish_scbs
  7. wdsintr
  8. wds_reset_scb
  9. wds_free_scb
  10. wds_free_buf
  11. wds_init_scb
  12. wds_get_scb
  13. wds_get_buf
  14. wds_scb_phys_kv
  15. wds_queue_scb
  16. wds_collect_mbo
  17. wds_start_scbs
  18. wds_done
  19. wds_find
  20. wds_init
  21. wds_inquire_setup_information
  22. wdsminphys
  23. wds_scsi_cmd
  24. VOLATILE_XS
  25. wds_poll
  26. wds_sense
  27. wds_poll
  28. wds_ipoll
  29. wds_timeout

    1 /*      $OpenBSD: wds.c,v 1.23 2006/11/28 23:59:45 dlg Exp $    */
    2 /*      $NetBSD: wds.c,v 1.13 1996/11/03 16:20:31 mycroft Exp $ */
    3 
    4 #undef  WDSDIAG
    5 #ifdef DDB
    6 #define integrate
    7 #else
    8 #define integrate       static inline
    9 #endif
   10 
   11 /*
   12  * XXX
   13  * sense data
   14  * aborts
   15  * resets
   16  */
   17 
   18 /*
   19  * Copyright (c) 1994, 1995 Julian Highfield.  All rights reserved.
   20  * Portions copyright (c) 1994, 1996 Charles M. Hannum.  All rights reserved.
   21  *
   22  * Redistribution and use in source and binary forms, with or without
   23  * modification, are permitted provided that the following conditions
   24  * are met:
   25  * 1. Redistributions of source code must retain the above copyright
   26  *    notice, this list of conditions and the following disclaimer.
   27  * 2. Redistributions in binary form must reproduce the above copyright
   28  *    notice, this list of conditions and the following disclaimer in the
   29  *    documentation and/or other materials provided with the distribution.
   30  * 3. All advertising materials mentioning features or use of this software
   31  *    must display the following acknowledgement:
   32  *      This product includes software developed by Julian Highfield.
   33  * 4. The name of the author may not be used to endorse or promote products
   34  *    derived from this software without specific prior written permission.
   35  *
   36  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   37  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   39  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   40  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   42  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   43  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   44  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   45  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   46  */
   47 
   48 /*
   49  * This driver is for the WD7000 family of SCSI controllers:
   50  *   the WD7000-ASC, a bus-mastering DMA controller,
   51  *   the WD7000-FASST2, an -ASC with new firmware and scatter-gather,
   52  *   and the WD7000-ASE, which was custom manufactured for Apollo
   53  *      workstations and seems to include an -ASC as well as floppy
   54  *      and ESDI interfaces.
   55  *
   56  * Loosely based on Theo Deraadt's unfinished attempt says the NetBSD group
   57  * so they decided to delete the copyright that file had on it.
   58  */
   59 
   60 #include <sys/types.h>
   61 #include <sys/param.h>
   62 #include <sys/systm.h>
   63 #include <sys/kernel.h>
   64 #include <sys/errno.h>
   65 #include <sys/ioctl.h>
   66 #include <sys/device.h>
   67 #include <sys/malloc.h>
   68 #include <sys/buf.h>
   69 #include <sys/proc.h>
   70 #include <sys/user.h>
   71 
   72 #include <machine/bus.h>
   73 #include <machine/intr.h>
   74 
   75 #include <scsi/scsi_all.h>
   76 #include <scsi/scsiconf.h>
   77 
   78 #include <dev/isa/isavar.h>
   79 #include <dev/isa/isadmavar.h>
   80 #include <dev/isa/wdsreg.h>
   81 
   82 #ifndef DDB
   83 #define Debugger() panic("should call debugger here (wds.c)")
   84 #endif /* ! DDB */
   85 
   86 #define WDS_MBX_SIZE    16
   87 
   88 #define WDS_SCB_MAX     32
   89 #define SCB_HASH_SIZE   32      /* hash table size for phystokv */
   90 #define SCB_HASH_SHIFT  9
   91 #define SCB_HASH(x)     ((((long)(x))>>SCB_HASH_SHIFT) & (SCB_HASH_SIZE - 1))
   92 
   93 #define wds_nextmbx(wmb, mbx, mbio) \
   94         if ((wmb) == &(mbx)->mbio[WDS_MBX_SIZE - 1])    \
   95                 (wmb) = &(mbx)->mbio[0];                \
   96         else                                            \
   97                 (wmb)++;
   98 
   99 struct wds_mbx {
  100         struct wds_mbx_out mbo[WDS_MBX_SIZE];
  101         struct wds_mbx_in mbi[WDS_MBX_SIZE];
  102         struct wds_mbx_out *cmbo;       /* Collection Mail Box out */
  103         struct wds_mbx_out *tmbo;       /* Target Mail Box out */
  104         struct wds_mbx_in *tmbi;        /* Target Mail Box in */
  105 };
  106 
  107 #define KVTOPHYS(x)     vtophys((vaddr_t)(x))
  108 
  109 struct wds_softc {
  110         struct device sc_dev;
  111         struct isadev sc_id;
  112         void *sc_ih;
  113 
  114         bus_space_tag_t sc_iot;         /* bus identifier */
  115         bus_space_handle_t sc_ioh;      /* io handle */
  116         int sc_irq, sc_drq;
  117 
  118         int sc_revision;
  119 
  120         struct wds_mbx sc_mbx;
  121 #define wmbx    (&sc->sc_mbx)
  122         struct wds_scb *sc_scbhash[SCB_HASH_SIZE];
  123         TAILQ_HEAD(, wds_scb) sc_free_scb, sc_waiting_scb;
  124         int sc_numscbs, sc_mbofull;
  125         int sc_scsi_dev;
  126         struct scsi_link sc_link;       /* prototype for subdevs */
  127 };
  128 
  129 /* Define the bounce buffer length... */
  130 #define BUFLEN (64*1024)
  131 /* ..and how many there are. One per device! Non-FASST boards need these. */
  132 #define BUFCNT 8
  133 /* The macro for deciding whether the board needs a buffer. */
  134 #define NEEDBUFFER(sc)  (sc->sc_revision < 0x800)
  135 
  136 struct wds_buf {
  137         u_char data[BUFLEN];
  138         int    busy;
  139         TAILQ_ENTRY(wds_buf) chain;
  140 } wds_buffer[BUFCNT];
  141 
  142 TAILQ_HEAD(, wds_buf) wds_free_buffer;
  143 
  144 #ifdef WDSDEBUG
  145 int wds_debug = WDSDEBUG;
  146 #endif
  147 
  148 integrate void    wds_wait(bus_space_tag_t, bus_space_handle_t, int, int, int);
  149 int     wds_cmd(struct wds_softc *, u_char *, int);
  150 integrate void wds_finish_scbs(struct wds_softc *);
  151 int     wdsintr(void *);
  152 integrate void wds_reset_scb(struct wds_softc *, struct wds_scb *);
  153 void    wds_free_scb(struct wds_softc *, struct wds_scb *);
  154 void    wds_free_buf(struct wds_softc *, struct wds_buf *);
  155 integrate void wds_init_scb(struct wds_softc *, struct wds_scb *);
  156 struct  wds_scb *wds_get_scb(struct wds_softc *, int, int);
  157 struct  wds_buf *wds_get_buf(struct wds_softc *, int);
  158 struct  wds_scb *wds_scb_phys_kv(struct wds_softc *, u_long);
  159 void    wds_queue_scb(struct wds_softc *, struct wds_scb *);
  160 void    wds_collect_mbo(struct wds_softc *);
  161 void    wds_start_scbs(struct wds_softc *);
  162 void    wds_done(struct wds_softc *, struct wds_scb *, u_char);
  163 int     wds_find(struct isa_attach_args *, struct wds_softc *);
  164 void    wds_init(struct wds_softc *);
  165 void    wds_inquire_setup_information(struct wds_softc *);
  166 void    wdsminphys(struct buf *);
  167 int     wds_scsi_cmd(struct scsi_xfer *);
  168 void    wds_sense(struct wds_softc *, struct wds_scb *);
  169 int     wds_poll(struct wds_softc *, struct scsi_xfer *, int);
  170 int     wds_ipoll(struct wds_softc *, struct wds_scb *, int);
  171 void    wds_timeout(void *);
  172 int     wdsprint(void *, const char *);
  173 
  174 struct scsi_adapter wds_switch = {
  175         wds_scsi_cmd,
  176         wdsminphys,
  177         0,
  178         0,
  179 };
  180 
  181 /* the below structure is so we have a default dev struct for our link struct */
  182 struct scsi_device wds_dev = {
  183         NULL,                   /* Use default error handler */
  184         NULL,                   /* have a queue, served by this */
  185         NULL,                   /* have no async handler */
  186         NULL,                   /* Use default 'done' routine */
  187 };
  188 
  189 int     wdsprobe(struct device *, void *, void *);
  190 void    wdsattach(struct device *, struct device *, void *);
  191 
  192 struct cfattach wds_ca = {
  193         sizeof(struct wds_softc), wdsprobe, wdsattach
  194 };
  195 
  196 struct cfdriver wds_cd = {
  197         NULL, "wds", DV_DULL
  198 };
  199 
  200 #define WDS_ABORT_TIMEOUT       2000    /* time to wait for abort (mSec) */
  201 
  202 integrate void
  203 wds_wait(iot, ioh, port, mask, val)
  204         bus_space_tag_t iot;
  205         bus_space_handle_t ioh;
  206         int port;
  207         int mask;
  208         int val;
  209 {
  210         while ((bus_space_read_1(iot, ioh, port) & mask) != val)
  211                 ;
  212 }
  213 
  214 /*
  215  * Write a command to the board's I/O ports.
  216  */
  217 int
  218 wds_cmd(sc, ibuf, icnt)
  219         struct wds_softc *sc;
  220         u_int8_t *ibuf;
  221         int icnt;
  222 {
  223         bus_space_tag_t iot = sc->sc_iot;
  224         bus_space_handle_t ioh = sc->sc_ioh;
  225         u_int8_t c;
  226 
  227         wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
  228 
  229         while (icnt--) {
  230                 bus_space_write_1(iot, ioh, WDS_CMD, *ibuf++);
  231                 wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
  232                 c = bus_space_read_1(iot, ioh, WDS_STAT);
  233                 if (c & WDSS_REJ)
  234                         return 1;
  235         }
  236 
  237         return 0;
  238 }
  239 
  240 /*
  241  * Check for the presence of a WD7000 SCSI controller.
  242  */
  243 int
  244 wdsprobe(parent, match, aux)
  245         struct device *parent;
  246         void *match, *aux;
  247 {
  248         register struct isa_attach_args *ia = aux;
  249         bus_space_tag_t iot = ia->ia_iot;
  250         bus_space_handle_t ioh;
  251         int rv;
  252 
  253         if (bus_space_map(iot, ia->ia_iobase, WDS_IO_PORTS, 0, &ioh))
  254                 return (0);
  255 
  256         /* See if there is a unit at this location. */
  257         rv = wds_find(ia, NULL);
  258 
  259         bus_space_unmap(iot, ioh, WDS_IO_PORTS);
  260 
  261         if (rv) {
  262                 ia->ia_msize = 0;
  263                 ia->ia_iosize = WDS_IO_PORTS;
  264         }
  265 
  266         return (rv);
  267 }
  268 
  269 int
  270 wdsprint(aux, name)
  271         void *aux;
  272         const char *name;
  273 {
  274 
  275         if (name != NULL)
  276                 printf("%s: scsibus ", name);
  277         return UNCONF;
  278 }
  279 
  280 /*
  281  * Attach all available units.
  282  */
  283 void
  284 wdsattach(parent, self, aux)
  285         struct device *parent, *self;
  286         void *aux;
  287 {
  288         struct isa_attach_args *ia = aux;
  289         struct wds_softc *sc = (void *)self;
  290         struct scsibus_attach_args saa;
  291         bus_space_tag_t iot = ia->ia_iot;
  292         bus_space_handle_t ioh;
  293 
  294         if (bus_space_map(iot, ia->ia_iobase, WDS_IO_PORTS, 0, &ioh)) {
  295                 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
  296                 return;
  297         }
  298 
  299         if (!wds_find(ia, sc))
  300                 panic("wdsattach: wds_find of %s failed", self->dv_xname);
  301         wds_init(sc);
  302 
  303         if (sc->sc_drq != DRQUNK)
  304                 isadma_cascade(sc->sc_drq);
  305 
  306         TAILQ_INIT(&sc->sc_free_scb);
  307         TAILQ_INIT(&sc->sc_waiting_scb);
  308         wds_inquire_setup_information(sc);
  309 
  310         /*
  311          * fill in the prototype scsi_link.
  312          */
  313 #ifdef notyet
  314         sc->sc_link.channel = SCSI_CHANNEL_ONLY_ONE;
  315 #endif
  316         sc->sc_link.adapter_softc = sc;
  317         sc->sc_link.adapter_target = sc->sc_scsi_dev;
  318         sc->sc_link.adapter = &wds_switch;
  319         sc->sc_link.device = &wds_dev;
  320         /* XXX */
  321         /* I don't think the -ASE can handle openings > 1. */
  322         /* It gives Vendor Error 26 whenever I try it.     */
  323         sc->sc_link.openings = 1;
  324 
  325         sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
  326             IPL_BIO, wdsintr, sc, sc->sc_dev.dv_xname);
  327 
  328         bzero(&saa, sizeof(saa));
  329         saa.saa_sc_link = &sc->sc_link;
  330 
  331         /*
  332          * ask the adapter what subunits are present
  333          */
  334         config_found(self, &saa, wdsprint);
  335 }
  336 
  337 integrate void
  338 wds_finish_scbs(sc)
  339         struct wds_softc *sc;
  340 {
  341         struct wds_mbx_in *wmbi;
  342         struct wds_scb *scb;
  343         int i;
  344 
  345         wmbi = wmbx->tmbi;
  346 
  347         if (wmbi->stat == WDS_MBI_FREE) {
  348                 for (i = 0; i < WDS_MBX_SIZE; i++) {
  349                         if (wmbi->stat != WDS_MBI_FREE) {
  350                                 printf("%s: mbi not in round-robin order\n",
  351                                     sc->sc_dev.dv_xname);
  352                                 goto AGAIN;
  353                         }
  354                         wds_nextmbx(wmbi, wmbx, mbi);
  355                 }
  356 #ifdef WDSDIAGnot
  357                 printf("%s: mbi interrupt with no full mailboxes\n",
  358                     sc->sc_dev.dv_xname);
  359 #endif
  360                 return;
  361         }
  362 
  363 AGAIN:
  364         do {
  365                 scb = wds_scb_phys_kv(sc, phystol(wmbi->scb_addr));
  366                 if (!scb) {
  367                         printf("%s: bad mbi scb pointer; skipping\n",
  368                             sc->sc_dev.dv_xname);
  369                         goto next;
  370                 }
  371 
  372 #ifdef WDSDEBUG
  373                 if (wds_debug) {
  374                         u_int8_t *cp = (u_int8_t *)&scb->cmd.scb;
  375                         printf("op=%x %x %x %x %x %x\n",
  376                             cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
  377                         printf("stat %x for mbi addr = 0x%08x, ",
  378                             wmbi->stat, wmbi);
  379                         printf("scb addr = 0x%x\n", scb);
  380                 }
  381 #endif /* WDSDEBUG */
  382 
  383                 timeout_del(&scb->xs->stimeout);
  384 #ifdef notyet
  385                 isadma_copyfrombuf((caddr_t)scb, SCB_PHYS_SIZE,
  386                     1, scb->scb_phys);
  387 #endif
  388                 wds_done(sc, scb, wmbi->stat);
  389 
  390         next:
  391                 wmbi->stat = WDS_MBI_FREE;
  392                 wds_nextmbx(wmbi, wmbx, mbi);
  393         } while (wmbi->stat != WDS_MBI_FREE);
  394 
  395         wmbx->tmbi = wmbi;
  396 }
  397 
  398 /*
  399  * Process an interrupt.
  400  */
  401 int
  402 wdsintr(arg)
  403         void *arg;
  404 {
  405         struct wds_softc *sc = arg;
  406         bus_space_tag_t iot = sc->sc_iot;
  407         bus_space_handle_t ioh = sc->sc_ioh;
  408         u_char c;
  409 
  410         /* Was it really an interrupt from the board? */
  411         if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ) == 0)
  412                 return 0;
  413 
  414         /* Get the interrupt status byte. */
  415         c = bus_space_read_1(iot, ioh, WDS_IRQSTAT) & WDSI_MASK;
  416 
  417         /* Acknowledge (which resets) the interrupt. */
  418         bus_space_write_1(iot, ioh, WDS_IRQACK, 0x00);
  419 
  420         switch (c) {
  421         case WDSI_MSVC:
  422                 wds_finish_scbs(sc);
  423                 break;
  424 
  425         case WDSI_MFREE:
  426                 wds_start_scbs(sc);
  427                 break;
  428 
  429         default:
  430                 printf("%s: unrecognized interrupt type %02x",
  431                     sc->sc_dev.dv_xname, c);
  432                 break;
  433         }
  434 
  435         return 1;
  436 }
  437 
  438 integrate void
  439 wds_reset_scb(sc, scb)
  440         struct wds_softc *sc;
  441         struct wds_scb *scb;
  442 {
  443 
  444         scb->flags = 0;
  445 }
  446 
  447 /*
  448  * Free the command structure, the outgoing mailbox and the data buffer.
  449  */
  450 void
  451 wds_free_scb(sc, scb)
  452         struct wds_softc *sc;
  453         struct wds_scb *scb;
  454 {
  455         int s;
  456 
  457         if (scb->buf != 0) {
  458                 wds_free_buf(sc, scb->buf);
  459                 scb->buf = 0;
  460         }
  461 
  462         s = splbio();
  463 
  464 #ifdef notyet
  465         if (scb->scb_phys[0].addr)
  466                 isadma_unmap((caddr_t)scb, SCB_PHYS_SIZE, 1, scb->scb_phys);
  467 #endif
  468 
  469         wds_reset_scb(sc, scb);
  470         TAILQ_INSERT_HEAD(&sc->sc_free_scb, scb, chain);
  471 
  472         /*
  473          * If there were none, wake anybody waiting for one to come free,
  474          * starting with queued entries.
  475          */
  476         if (TAILQ_NEXT(scb, chain) == NULL)
  477                 wakeup(&sc->sc_free_scb);
  478 
  479         splx(s);
  480 }
  481 
  482 void
  483 wds_free_buf(sc, buf)
  484         struct wds_softc *sc;
  485         struct wds_buf *buf;
  486 {
  487         int s;
  488 
  489         s = splbio();
  490 
  491         buf->busy = 0;
  492         TAILQ_INSERT_HEAD(&wds_free_buffer, buf, chain);
  493 
  494         /*
  495          * If there were none, wake anybody waiting for one to come free,
  496          * starting with queued entries.
  497          */
  498         if (TAILQ_NEXT(buf, chain) == NULL)
  499                 wakeup(&wds_free_buffer);
  500 
  501         splx(s);
  502 }
  503 
  504 integrate void
  505 wds_init_scb(sc, scb)
  506         struct wds_softc *sc;
  507         struct wds_scb *scb;
  508 {
  509         int hashnum;
  510 
  511         bzero(scb, sizeof(struct wds_scb));
  512         /*
  513          * put in the phystokv hash table
  514          * Never gets taken out.
  515          */
  516         scb->hashkey = KVTOPHYS(scb);
  517         hashnum = SCB_HASH(scb->hashkey);
  518         scb->nexthash = sc->sc_scbhash[hashnum];
  519         sc->sc_scbhash[hashnum] = scb;
  520         wds_reset_scb(sc, scb);
  521 }
  522 
  523 /*
  524  * Get a free scb
  525  *
  526  * If there are none, see if we can allocate a new one.  If so, put it in
  527  * the hash table too otherwise either return an error or sleep.
  528  */
  529 struct wds_scb *
  530 wds_get_scb(sc, flags, needbuffer)
  531         struct wds_softc *sc;
  532         int flags;
  533         int needbuffer;
  534 {
  535         struct wds_scb *scb;
  536         int s;
  537 #ifdef notyet
  538         int mflags, hashnum;
  539 #endif
  540 
  541         s = splbio();
  542 
  543 #ifdef notyet
  544         if (flags & SCSI_NOSLEEP)
  545                 mflags = ISADMA_MAP_BOUNCE;
  546         else
  547                 mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
  548 #endif
  549 
  550         /*
  551          * If we can and have to, sleep waiting for one to come free
  552          * but only if we can't allocate a new one.
  553          */
  554         for (;;) {
  555                 scb = TAILQ_FIRST(&sc->sc_free_scb);
  556                 if (scb) {
  557                         TAILQ_REMOVE(&sc->sc_free_scb, scb, chain);
  558                         break;
  559                 }
  560                 if (sc->sc_numscbs < WDS_SCB_MAX) {
  561                         scb = (struct wds_scb *) malloc(sizeof(struct wds_scb),
  562                             M_TEMP, M_NOWAIT);
  563                         if (!scb) {
  564                                 printf("%s: can't malloc scb\n",
  565                                     sc->sc_dev.dv_xname);
  566                                 goto out;
  567                         }
  568                         wds_init_scb(sc, scb);
  569                         sc->sc_numscbs++;
  570                         break;
  571                 }
  572                 if ((flags & SCSI_NOSLEEP) != 0)
  573                         goto out;
  574                 tsleep(&sc->sc_free_scb, PRIBIO, "wdsscb", 0);
  575         }
  576 
  577         scb->flags |= SCB_ALLOC;
  578 
  579 #ifdef notyet
  580         if (isadma_map((caddr_t)scb, SCB_PHYS_SIZE, scb->scb_phys,
  581             mflags | ISADMA_MAP_CONTIG) == 1) {
  582                 hashnum = SCB_HASH(scb->scb_phys[0].addr);
  583                 scb->nexthash = sc->sc_scbhash[hashnum];
  584                 sc->sc_scbhash[hashnum] = ccb;
  585         } else {
  586                 scb->scb_phys[0].addr = 0;
  587                 wds_free_scb(sc, scb);
  588                 scb = 0;
  589         }
  590 #else
  591         if (needbuffer) {
  592                 scb->buf = wds_get_buf(sc, flags);
  593                 if (scb->buf == 0) {
  594                         wds_free_scb(sc, scb);
  595                         scb = 0;
  596                 }
  597         }
  598 #endif
  599 
  600 
  601 out:
  602         splx(s);
  603         return (scb);
  604 }
  605 
  606 struct wds_buf *
  607 wds_get_buf(sc, flags)
  608         struct wds_softc *sc;
  609         int flags;
  610 {
  611         struct wds_buf *buf;
  612         int s;
  613 
  614         s = splbio();
  615 
  616         for (;;) {
  617                 buf = TAILQ_FIRST(&wds_free_buffer);
  618                 if (buf) {
  619                         TAILQ_REMOVE(&wds_free_buffer, buf, chain);
  620                         break;
  621                 }
  622                 if ((flags & SCSI_NOSLEEP) != 0)
  623                         goto out;
  624                 tsleep(&wds_free_buffer, PRIBIO, "wdsbuf", 0);
  625         }
  626 
  627         buf->busy = 1;
  628 
  629 out:
  630         splx(s);
  631         return (buf);
  632 }
  633 
  634 struct wds_scb *
  635 wds_scb_phys_kv(sc, scb_phys)
  636         struct wds_softc *sc;
  637         u_long scb_phys;
  638 {
  639         int hashnum = SCB_HASH(scb_phys);
  640         struct wds_scb *scb = sc->sc_scbhash[hashnum];
  641 
  642         while (scb) {
  643                 if (scb->hashkey == scb_phys)
  644                         break;
  645                 /* XXX Check to see if it matches the sense command block. */
  646                 if (scb->hashkey == (scb_phys - sizeof(struct wds_cmd)))
  647                         break;
  648                 scb = scb->nexthash;
  649         }
  650         return scb;
  651 }
  652 
  653 /*
  654  * Queue a SCB to be sent to the controller, and send it if possible.
  655  */
  656 void
  657 wds_queue_scb(sc, scb)
  658         struct wds_softc *sc;
  659         struct wds_scb *scb;
  660 {
  661 
  662         TAILQ_INSERT_TAIL(&sc->sc_waiting_scb, scb, chain);
  663         wds_start_scbs(sc);
  664 }
  665 
  666 /*
  667  * Garbage collect mailboxes that are no longer in use.
  668  */
  669 void
  670 wds_collect_mbo(sc)
  671         struct wds_softc *sc;
  672 {
  673         struct wds_mbx_out *wmbo;       /* Mail Box Out pointer */
  674 #ifdef WDSDIAG
  675         struct wds_scb *scb;
  676 #endif
  677 
  678         wmbo = wmbx->cmbo;
  679 
  680         while (sc->sc_mbofull > 0) {
  681                 if (wmbo->cmd != WDS_MBO_FREE)
  682                         break;
  683 
  684 #ifdef WDSDIAG
  685                 scb = wds_scb_phys_kv(sc, phystol(wmbo->scb_addr));
  686                 scb->flags &= ~SCB_SENDING;
  687 #endif
  688 
  689                 --sc->sc_mbofull;
  690                 wds_nextmbx(wmbo, wmbx, mbo);
  691         }
  692 
  693         wmbx->cmbo = wmbo;
  694 }
  695 
  696 /*
  697  * Send as many SCBs as we have empty mailboxes for.
  698  */
  699 void
  700 wds_start_scbs(sc)
  701         struct wds_softc *sc;
  702 {
  703         struct wds_mbx_out *wmbo;       /* Mail Box Out pointer */
  704         struct wds_scb *scb;
  705         u_char c;
  706 
  707         wmbo = wmbx->tmbo;
  708 
  709         while ((scb = TAILQ_FIRST(&sc->sc_waiting_scb)) != NULL) {
  710                 if (sc->sc_mbofull >= WDS_MBX_SIZE) {
  711                         wds_collect_mbo(sc);
  712                         if (sc->sc_mbofull >= WDS_MBX_SIZE) {
  713                                 c = WDSC_IRQMFREE;
  714                                 wds_cmd(sc, &c, sizeof c);
  715                                 break;
  716                         }
  717                 }
  718 
  719                 TAILQ_REMOVE(&sc->sc_waiting_scb, scb, chain);
  720 #ifdef WDSDIAG
  721                 scb->flags |= SCB_SENDING;
  722 #endif
  723 
  724                 /* Link scb to mbo. */
  725 #ifdef notyet
  726                 isadma_copytobuf((caddr_t)scb, SCB_PHYS_SIZE,
  727                     1, scb->scb_phys);
  728                 ltophys(scb->scb_phys[0].addr, wmbo->scb_addr);
  729 #else
  730                 if (scb->flags & SCB_SENSE)
  731                         ltophys(KVTOPHYS(&scb->sense), wmbo->scb_addr);
  732                 else
  733                         ltophys(KVTOPHYS(&scb->cmd), wmbo->scb_addr);
  734 #endif
  735                 /* XXX What about aborts? */
  736                 wmbo->cmd = WDS_MBO_START;
  737 
  738                 /* Tell the card to poll immediately. */
  739                 c = WDSC_MSTART(wmbo - wmbx->mbo);
  740                 wds_cmd(sc, &c, sizeof c);
  741 
  742                 if ((scb->flags & SCB_POLLED) == 0) {
  743                         timeout_set(&scb->xs->stimeout, wds_timeout, scb);
  744                         timeout_add(&scb->xs->stimeout, (scb->timeout * hz) / 1000);
  745                 }
  746 
  747                 ++sc->sc_mbofull;
  748                 wds_nextmbx(wmbo, wmbx, mbo);
  749         }
  750 
  751         wmbx->tmbo = wmbo;
  752 }
  753 
  754 /*
  755  * Process the result of a SCSI command.
  756  */
  757 void
  758 wds_done(sc, scb, stat)
  759         struct wds_softc *sc;
  760         struct wds_scb *scb;
  761         u_int8_t stat;
  762 {
  763         struct scsi_xfer *xs = scb->xs;
  764 
  765         /* XXXXX */
  766 
  767         /* Don't release the SCB if it was an internal command. */
  768         if (xs == 0) {
  769                 scb->flags |= SCB_DONE;
  770                 return;
  771         }
  772 
  773         /* Sense handling. */
  774         if (xs->error == XS_SENSE) {
  775                 bcopy(&scb->sense_data, &xs->sense, sizeof (struct scsi_sense_data));
  776         } else {
  777                 if (xs->error == XS_NOERROR) {
  778                         /* If all went well, or an error is acceptable. */
  779                         if (stat == WDS_MBI_OK) {
  780                                 /* OK, set the result */
  781                                 xs->resid = 0;
  782                         } else {
  783                                 /* Check the mailbox status. */
  784                                 switch (stat) {
  785                                 case WDS_MBI_OKERR:
  786                                         /* SCSI error recorded in scb, counts as WDS_MBI_OK */
  787                                         switch (scb->cmd.venderr) {
  788                                         case 0x00:
  789                                                 printf("%s: Is this an error?\n", sc->sc_dev.dv_xname);
  790                                                 xs->error = XS_DRIVER_STUFFUP; /* Experiment */
  791                                                 break;
  792                                         case 0x01:
  793                                                 /*printf("%s: OK, see SCSI error field.\n", sc->sc_dev.dv_xname);*/
  794                                                 if (scb->cmd.stat == SCSI_CHECK) {
  795                                                         /* Do sense. */
  796                                                         wds_sense (sc, scb);
  797                                                         return;
  798                                                 } else if (scb->cmd.stat == SCSI_BUSY) {
  799                                                         xs->error = XS_BUSY;
  800                                                 }
  801                                                 break;
  802                                         case 0x40:
  803                                                 /*printf("%s: DMA underrun!\n", sc->sc_dev.dv_xname);*/
  804                                                 /* Hits this if the target returns fewer that datalen bytes (eg my CD-ROM,
  805                                                 which returns a short version string, or if DMA is turned off etc. */
  806                                                 xs->resid = 0;
  807                                                 break;
  808                                         default:
  809                                                 printf("%s: VENDOR ERROR %02x, scsi %02x\n", sc->sc_dev.dv_xname, scb->cmd.venderr, scb->cmd.stat);
  810                                                 xs->error = XS_DRIVER_STUFFUP; /* Experiment */
  811                                                 break;
  812                                         }
  813                                         break;
  814                                 case WDS_MBI_ETIME:
  815                                         /*
  816                                          * The documentation isn't clear on
  817                                          * what conditions might generate this,
  818                                          * but selection timeouts are the only
  819                                          * one I can think of.
  820                                          */
  821                                         xs->error = XS_SELTIMEOUT;
  822                                         break;
  823                                 case WDS_MBI_ERESET:
  824                                 case WDS_MBI_ETARCMD:
  825                                 case WDS_MBI_ERESEL:
  826                                 case WDS_MBI_ESEL:
  827                                 case WDS_MBI_EABORT:
  828                                 case WDS_MBI_ESRESET:
  829                                 case WDS_MBI_EHRESET:
  830                                         xs->error = XS_DRIVER_STUFFUP;
  831                                         break;
  832                                 }
  833                         }
  834                 } /* else sense */
  835 
  836                 if (NEEDBUFFER(sc) && xs->datalen) {
  837                         if (xs->flags & SCSI_DATA_IN)
  838                                 bcopy(scb->buf->data, xs->data, xs->datalen);
  839                 }
  840         } /* XS_NOERROR */
  841 
  842 #ifdef notyet
  843         if (scb->data_nseg) {
  844                 if (xs->flags & SCSI_DATA_IN)
  845                         isadma_copyfrombuf(xs->data, xs->datalen,
  846                             scb->data_nseg, scb->data_phys);
  847                 isadma_unmap(xs->data, xs->datalen,
  848                     scb->data_nseg, scb->data_phys);
  849         }
  850 #endif
  851         wds_free_scb(sc, scb);
  852         xs->flags |= ITSDONE;
  853         scsi_done(xs);
  854 }
  855 
  856 int
  857 wds_find(ia, sc)
  858         struct isa_attach_args *ia;
  859         struct wds_softc *sc;
  860 {
  861         bus_space_tag_t iot = ia->ia_iot;
  862         bus_space_handle_t ioh;
  863         u_char c;
  864         int i;
  865 
  866         /*
  867          * Sending a command causes the CMDRDY bit to clear.
  868          */
  869         c = bus_space_read_1(iot, ioh, WDS_STAT);
  870         for (i = 0; i < 4; i++)
  871                 if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_RDY) != 0) {
  872                         goto ready;
  873                 delay(10);
  874         }
  875         return (0);
  876 
  877 ready:
  878         bus_space_write_1(iot, ioh, WDS_CMD, WDSC_NOOP);
  879         if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_RDY)
  880                 return (0);
  881 
  882         bus_space_write_1(iot, ioh, WDS_HCR, WDSH_SCSIRESET|WDSH_ASCRESET);
  883         delay(10000);
  884         bus_space_write_1(iot, ioh, WDS_HCR, 0x00);
  885         delay(500000);
  886         wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY);
  887         if (bus_space_read_1(iot, ioh, WDS_IRQSTAT) != 1)
  888                 if (bus_space_read_1(iot, ioh, WDS_IRQSTAT) != 7)
  889                         printf("%s: failed reset!!! %2x\n",
  890                             sc ? sc->sc_dev.dv_xname : "wds?",
  891                             bus_space_read_1(iot, ioh, WDS_IRQSTAT));
  892 
  893         if ((bus_space_read_1(iot, ioh, WDS_STAT) & (WDSS_RDY)) != WDSS_RDY) {
  894                 printf("%s: waiting for controller to become ready.",
  895                     sc ? sc->sc_dev.dv_xname : "wds?");
  896                 for (i = 0; i < 20; i++) {
  897                         if ((bus_space_read_1(iot, ioh, WDS_STAT) &
  898                             (WDSS_RDY)) == WDSS_RDY)
  899                                 break;
  900                         printf(".");
  901                         delay(10000);
  902                 }
  903                 if ((bus_space_read_1(iot, ioh, WDS_STAT) & (WDSS_RDY)) !=
  904                     WDSS_RDY) {
  905                         printf(" failed\n");
  906                         return (0);
  907                 }
  908                 printf("\n");
  909         }
  910 
  911         if (sc != NULL) {
  912                 /* XXX Can we do this better? */
  913                 /* who are we on the scsi bus? */
  914                 sc->sc_scsi_dev = 7;
  915 
  916                 sc->sc_iot = iot;
  917                 sc->sc_ioh = ioh;
  918                 sc->sc_irq = ia->ia_irq;
  919                 sc->sc_drq = ia->ia_drq;
  920         }
  921 
  922         return (1);
  923 }
  924 
  925 /*
  926  * Initialise the board and driver.
  927  */
  928 void
  929 wds_init(sc)
  930         struct wds_softc *sc;
  931 {
  932         bus_space_tag_t iot = sc->sc_iot;
  933         bus_space_handle_t ioh = sc->sc_ioh;
  934         struct wds_setup init;
  935         u_char c;
  936         int i;
  937 #ifdef notyet
  938         struct isadma_seg mbx_phys[1];
  939 #endif
  940 
  941         /*
  942          * Set up initial mail box for round-robin operation.
  943          */
  944         for (i = 0; i < WDS_MBX_SIZE; i++) {
  945                 wmbx->mbo[i].cmd = WDS_MBO_FREE;
  946                 wmbx->mbi[i].stat = WDS_MBI_FREE;
  947         }
  948         wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
  949         wmbx->tmbi = &wmbx->mbi[0];
  950         sc->sc_mbofull = 0;
  951 
  952         /* Clear the buffers. */
  953         TAILQ_INIT(&wds_free_buffer);
  954         for (i = 0; i < BUFCNT; i++) {
  955                 wds_buffer[i].busy = 0;
  956                 TAILQ_INSERT_HEAD(&wds_free_buffer, &wds_buffer[i], chain);
  957         }
  958 
  959         init.opcode = WDSC_INIT;
  960         init.scsi_id = sc->sc_scsi_dev;
  961         /* Record scsi id of controller for use in scsi_attach */
  962         sc->sc_scsi_dev = init.scsi_id;
  963         init.buson_t = 48;
  964         init.busoff_t = 24;
  965         init.xx = 0;
  966 #ifdef notyet
  967         if (isadma_map((caddr_t)(wmbx), sizeof(struct wds_mbx),
  968             mbx_phys, ISADMA_MAP_CONTIG) != 1)
  969                 panic("wds_init: cannot map mail box");
  970         ltophys(mbx_phys[0].addr, init.mbaddr);
  971 #else
  972         ltophys(KVTOPHYS(wmbx), init.mbaddr);
  973 #endif
  974         init.nomb = init.nimb = WDS_MBX_SIZE;
  975         wds_cmd(sc, (u_char *)&init, sizeof init);
  976 
  977         wds_wait(iot, ioh, WDS_STAT, WDSS_INIT, WDSS_INIT);
  978 
  979         c = WDSC_DISUNSOL;
  980         wds_cmd(sc, &c, sizeof c);
  981 
  982         bus_space_write_1(iot, ioh, WDS_HCR, WDSH_DRQEN);
  983 }
  984 
  985 /*
  986  * Read the board's firmware revision information.
  987  */
  988 void
  989 wds_inquire_setup_information(sc)
  990         struct wds_softc *sc;
  991 {
  992         struct wds_scb *scb;
  993         u_char *j;
  994         int s;
  995 
  996         if ((scb = wds_get_scb(sc, SCSI_NOSLEEP, 0)) == NULL) {
  997                 printf("%s: no request slot available in getvers()!\n",
  998                     sc->sc_dev.dv_xname);
  999                 return;
 1000         }
 1001         scb->xs = NULL;
 1002         scb->timeout = 40;
 1003 
 1004         bzero(&scb->cmd, sizeof scb->cmd);
 1005         scb->cmd.write = 0x80;
 1006         scb->cmd.opcode = WDSX_GETFIRMREV;
 1007 
 1008         /* Will poll card, await result. */
 1009         bus_space_write_1(sc->sc_iot, sc->sc_ioh, WDS_HCR, WDSH_DRQEN);
 1010         scb->flags |= SCB_POLLED;
 1011 
 1012         s = splbio();
 1013         wds_queue_scb(sc, scb);
 1014         splx(s);
 1015 
 1016         if (wds_ipoll(sc, scb, scb->timeout))
 1017                 goto out;
 1018 
 1019         /* Print the version number. */
 1020         printf(": version %x.%02x ", scb->cmd.targ, scb->cmd.scb.opcode);
 1021         sc->sc_revision = (scb->cmd.targ << 8) | scb->cmd.scb.opcode;
 1022         /* Print out the version string. */
 1023         j = 2 + &(scb->cmd.targ);
 1024         while ((*j >= 32) && (*j < 128)) {
 1025                 printf("%c", *j);
 1026                 j++;
 1027         }
 1028 
 1029 out:
 1030         printf("\n");
 1031         wds_free_scb(sc, scb);
 1032 }
 1033 
 1034 void
 1035 wdsminphys(bp)
 1036         struct buf *bp;
 1037 {
 1038         if (bp->b_bcount > ((WDS_NSEG - 1) << PGSHIFT))
 1039                 bp->b_bcount = ((WDS_NSEG - 1) << PGSHIFT);
 1040         minphys(bp);
 1041 }
 1042 
 1043 /*
 1044  * Send a SCSI command.
 1045  */
 1046 int
 1047 wds_scsi_cmd(xs)
 1048         struct scsi_xfer *xs;
 1049 {
 1050         struct scsi_link *sc_link = xs->sc_link;
 1051         struct wds_softc *sc = sc_link->adapter_softc;
 1052         bus_space_tag_t iot = sc->sc_iot;
 1053         bus_space_handle_t ioh = sc->sc_ioh;
 1054         struct wds_scb *scb;
 1055         struct wds_scat_gath *sg;
 1056         int seg;
 1057         u_long thiskv, thisphys, nextphys;
 1058         int bytes_this_seg, bytes_this_page, datalen, flags;
 1059 #ifdef TFS
 1060         struct iovec *iovp;
 1061 #endif
 1062         int s;
 1063 #ifdef notyet
 1064         int mflags;
 1065 #endif
 1066 
 1067         if (xs->flags & SCSI_RESET) {
 1068                 /* XXX Fix me! */
 1069                 printf("%s: reset!\n", sc->sc_dev.dv_xname);
 1070                 wds_init(sc);
 1071                 return COMPLETE;
 1072         }
 1073 
 1074         flags = xs->flags;
 1075 #ifdef notyet
 1076         if (flags & SCSI_NOSLEEP)
 1077                 mflags = ISADMA_MAP_BOUNCE;
 1078         else
 1079                 mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK;
 1080 #endif
 1081         if ((scb = wds_get_scb(sc, flags, NEEDBUFFER(sc))) == NULL) {
 1082                 return TRY_AGAIN_LATER;
 1083         }
 1084         scb->xs = xs;
 1085         scb->timeout = xs->timeout;
 1086 
 1087         if (xs->flags & SCSI_DATA_UIO) {
 1088                 /* XXX Fix me! */
 1089                 /* Let's not worry about UIO. There isn't any code for the *
 1090                  * non-SG boards anyway! */
 1091                 printf("%s: UIO is untested and disabled!\n", sc->sc_dev.dv_xname);
 1092                 goto bad;
 1093         }
 1094 
 1095         /* Zero out the command structure. */
 1096         bzero(&scb->cmd, sizeof scb->cmd);
 1097         bcopy(xs->cmd, &scb->cmd.scb, xs->cmdlen < 12 ? xs->cmdlen : 12);
 1098 
 1099         /* Set up some of the command fields. */
 1100         scb->cmd.targ = (xs->sc_link->target << 5) | xs->sc_link->lun;
 1101 
 1102         /* NOTE: cmd.write may be OK as 0x40 (disable direction checking)
 1103          * on boards other than the WD-7000V-ASE. Need this for the ASE:
 1104          */
 1105         scb->cmd.write = (xs->flags & SCSI_DATA_IN) ? 0x80 : 0x00;
 1106 
 1107         if (!NEEDBUFFER(sc) && xs->datalen) {
 1108                 sg = scb->scat_gath;
 1109                 seg = 0;
 1110 #ifdef TFS
 1111                 if (flags & SCSI_DATA_UIO) {
 1112                         iovp = ((struct uio *)xs->data)->uio_iov;
 1113                         datalen = ((struct uio *)xs->data)->uio_iovcnt;
 1114                         xs->datalen = 0;
 1115                         while (datalen && seg < WDS_NSEG) {
 1116                                 ltophys(iovp->iov_base, sg->seg_addr);
 1117                                 ltophys(iovp->iov_len, sg->seg_len);
 1118                                 xs->datalen += iovp->iov_len;
 1119                                 SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
 1120                                     iovp->iov_len, iovp->iov_base));
 1121                                 sg++;
 1122                                 iovp++;
 1123                                 seg++;
 1124                                 datalen--;
 1125                         }
 1126                 } else
 1127 #endif /* TFS */
 1128                 {
 1129                         /*
 1130                          * Set up the scatter-gather block.
 1131                          */
 1132                         SC_DEBUG(sc_link, SDEV_DB4,
 1133                             ("%d @0x%x:- ", xs->datalen, xs->data));
 1134 
 1135 #ifdef notyet
 1136                         scb->data_nseg = isadma_map(xs->data, xs->datalen,
 1137                                                     scb->data_phys, mflags);
 1138                         for (seg = 0; seg < scb->data_nseg; seg++) {
 1139                                 ltophys(scb->data_phys[seg].addr,
 1140                                        sg[seg].seg_addr);
 1141                                 ltophys(scb->data_phys[seg].length,
 1142                                        sg[seg].seg_len);
 1143                         }
 1144 #else
 1145                         datalen = xs->datalen;
 1146                         thiskv = (int)xs->data;
 1147                         thisphys = KVTOPHYS(xs->data);
 1148 
 1149                         while (datalen && seg < WDS_NSEG) {
 1150                                 bytes_this_seg = 0;
 1151 
 1152                                 /* put in the base address */
 1153                                 ltophys(thisphys, sg->seg_addr);
 1154 
 1155                                 SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
 1156 
 1157                                 /* do it at least once */
 1158                                 nextphys = thisphys;
 1159                                 while (datalen && thisphys == nextphys) {
 1160                                         /*
 1161                                          * This page is contiguous (physically)
 1162                                          * with the last, just extend the
 1163                                          * length
 1164                                          */
 1165                                         /* check it fits on the ISA bus */
 1166                                         if (thisphys > 0xFFFFFF) {
 1167                                                 printf("%s: DMA beyond"
 1168                                                         " end of ISA\n",
 1169                                                         sc->sc_dev.dv_xname);
 1170                                                 goto bad;
 1171                                         }
 1172                                         /* how far to the end of the page */
 1173                                         nextphys = (thisphys & ~PGOFSET) + NBPG;
 1174                                         bytes_this_page = nextphys - thisphys;
 1175                                         /**** or the data ****/
 1176                                         bytes_this_page = min(bytes_this_page,
 1177                                                               datalen);
 1178                                         bytes_this_seg += bytes_this_page;
 1179                                         datalen -= bytes_this_page;
 1180 
 1181                                         /* get more ready for the next page */
 1182                                         thiskv = (thiskv & ~PGOFSET) + NBPG;
 1183                                         if (datalen)
 1184                                                 thisphys = KVTOPHYS(thiskv);
 1185                                 }
 1186                                 /*
 1187                                  * next page isn't contiguous, finish the seg
 1188                                  */
 1189                                 SC_DEBUGN(sc_link, SDEV_DB4,
 1190                                     ("(0x%x)", bytes_this_seg));
 1191                                 ltophys(bytes_this_seg, sg->seg_len);
 1192                                 sg++;
 1193                                 seg++;
 1194 #endif
 1195                         }
 1196                 }
 1197                 /* end of iov/kv decision */
 1198                 SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
 1199                 if (datalen) {
 1200                         /*
 1201                          * there's still data, must have run out of segs!
 1202                          */
 1203                         printf("%s: wds_scsi_cmd, more than %d dma segs\n",
 1204                             sc->sc_dev.dv_xname, WDS_NSEG);
 1205                         goto bad;
 1206                 }
 1207 #ifdef notyet
 1208                 if (scb->data_nseg == 0) {
 1209                         printf("%s: wds_scsi_cmd, cannot map\n",
 1210                                sc->sc_dev.dv_xname);
 1211                         goto bad;
 1212                 } else if (flags & SCSI_DATA_OUT)
 1213                         isadma_copytobuf(xs->data, xs->datalen,
 1214                                          scb->data_nseg, scb->data_phys);
 1215                 ltophys((unsigned)((struct wds_scb *)(scb->scb_phys[0].addr))->scat_gath,
 1216                         scb->data_addr);
 1217                 ltophys(scb->data_nseg * sizeof(struct wds_scat_gath),
 1218                         scb->data_length);
 1219 #else
 1220                 scb->cmd.opcode = WDSX_SCSISG;
 1221                 ltophys(KVTOPHYS(scb->scat_gath), scb->cmd.data);
 1222                 ltophys(seg * sizeof(struct wds_scat_gath), scb->cmd.len);
 1223 #endif
 1224         } else if (xs->datalen > 0) {
 1225                 /* The board is an ASC or ASE. Do not use scatter/gather. */
 1226                 if (xs->datalen > BUFLEN) {
 1227                         printf("%s: wds_scsi_cmd, I/O too large for bounce buffer\n",
 1228                             sc->sc_dev.dv_xname);
 1229                         goto bad;
 1230                 }
 1231                 if (xs->flags & SCSI_DATA_OUT)
 1232                         bcopy(xs->data, scb->buf->data, xs->datalen);
 1233                 else
 1234                         bzero(scb->buf->data, xs->datalen);
 1235                 scb->cmd.opcode = WDSX_SCSICMD;
 1236                 ltophys(KVTOPHYS(scb->buf->data), scb->cmd.data);
 1237                 ltophys(xs->datalen, scb->cmd.len);
 1238         } else {
 1239                 scb->cmd.opcode = WDSX_SCSICMD;
 1240                 ltophys(0, scb->cmd.data);
 1241                 ltophys(0, scb->cmd.len);
 1242         }
 1243 
 1244         scb->cmd.stat = 0x00;
 1245         scb->cmd.venderr = 0x00;
 1246         ltophys(0, scb->cmd.link);
 1247 
 1248         /* XXX Do we really want to do this? */
 1249         if (flags & SCSI_POLL) {
 1250                 /* Will poll card, await result. */
 1251                 bus_space_write_1(iot, ioh, WDS_HCR, WDSH_DRQEN);
 1252                 scb->flags |= SCB_POLLED;
 1253         } else {
 1254                 /* Will send command, let interrupt routine handle result. */
 1255                 bus_space_write_1(iot, ioh, WDS_HCR, WDSH_IRQEN | WDSH_DRQEN);
 1256         }
 1257 
 1258         s = splbio();
 1259         wds_queue_scb(sc, scb);
 1260 
 1261 #ifdef notyet
 1262         if (VOLATILE_XS(xs)) {
 1263                 while ((scb->xs->flags & ITSDONE) == 0) {
 1264                         tsleep(scb, PRIBIO, "wdswait", 0);
 1265                 }
 1266                 if (scb->data_nseg) {
 1267                         if (flags & SCSI_DATA_IN)
 1268                                 isadma_copyfrombuf(xs->data, xs->datalen,
 1269                                     scb->data_nseg, scb->data_phys);
 1270                         isadma_unmap(xs->data, xs->datalen,
 1271                             scb->data_nseg, scb->data_phys);
 1272                 }
 1273                 wds_free_scb(sc, scb);
 1274                 scsi_done(xs);
 1275                 splx(s);
 1276                 return COMPLETE;
 1277         }
 1278 #endif
 1279         splx(s);
 1280 
 1281         if ((flags & SCSI_POLL) == 0)
 1282                 return SUCCESSFULLY_QUEUED;
 1283 
 1284         if (wds_poll(sc, xs, scb->timeout)) {
 1285                 wds_timeout(scb);
 1286                 if (wds_poll(sc, xs, scb->timeout))
 1287                         wds_timeout(scb);
 1288         }
 1289         return COMPLETE;
 1290 
 1291 bad:
 1292         xs->error = XS_DRIVER_STUFFUP;
 1293         wds_free_scb(sc, scb);
 1294         return COMPLETE;
 1295 }
 1296 
 1297 /*
 1298  * Send a sense request.
 1299  */
 1300 void
 1301 wds_sense(sc, scb)
 1302         struct wds_softc *sc;
 1303         struct wds_scb *scb;
 1304 {
 1305         struct scsi_xfer *xs = scb->xs;
 1306         struct scsi_sense *ss = (void *)&scb->sense.scb;
 1307         int s;
 1308 
 1309         /* XXXXX */
 1310 
 1311         /* Send sense request SCSI command. */
 1312         xs->error = XS_SENSE;
 1313         scb->flags |= SCB_SENSE;
 1314 
 1315         /* First, save the return values */
 1316         if (NEEDBUFFER(sc) && xs->datalen) {
 1317                 if (xs->flags & SCSI_DATA_IN)
 1318                         bcopy(scb->buf->data, xs->data, xs->datalen);
 1319         }
 1320 
 1321         /* Next, setup a request sense command block */
 1322         bzero(ss, sizeof(*ss));
 1323         ss->opcode = REQUEST_SENSE;
 1324         ss->byte2 = xs->sc_link->lun << 5;
 1325         ss->length = sizeof(struct scsi_sense_data);
 1326 
 1327         /* Set up some of the command fields. */
 1328         scb->sense.targ = scb->cmd.targ;
 1329         scb->sense.write = 0x80;
 1330         scb->sense.opcode = WDSX_SCSICMD;
 1331         ltophys(KVTOPHYS(&scb->sense_data), scb->sense.data);
 1332         ltophys(sizeof(struct scsi_sense_data), scb->sense.len);
 1333 
 1334         s = splbio();
 1335         wds_queue_scb(sc, scb);
 1336         splx(s);
 1337 
 1338         /*
 1339          * There's no reason for us to poll here.  There are two cases:
 1340          * 1) If it's a polling operation, then we're called from the interrupt
 1341          *    handler, and we return and continue polling.
 1342          * 2) If it's an interrupt-driven operation, then it gets completed
 1343          *    later on when the REQUEST SENSE finishes.
 1344          */
 1345 }
 1346 
 1347 /*
 1348  * Poll a particular unit, looking for a particular scb
 1349  */
 1350 int
 1351 wds_poll(sc, xs, count)
 1352         struct wds_softc *sc;
 1353         struct scsi_xfer *xs;
 1354         int count;
 1355 {
 1356         bus_space_tag_t iot = sc->sc_iot;
 1357         bus_space_handle_t ioh = sc->sc_ioh;
 1358 
 1359         /* timeouts are in msec, so we loop in 1000 usec cycles */
 1360         while (count) {
 1361                 /*
 1362                  * If we had interrupts enabled, would we
 1363                  * have got an interrupt?
 1364                  */
 1365                 if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ)
 1366                         wdsintr(sc);
 1367                 if (xs->flags & ITSDONE)
 1368                         return 0;
 1369                 delay(1000);    /* only happens in boot so ok */
 1370                 count--;
 1371         }
 1372         return 1;
 1373 }
 1374 
 1375 /*
 1376  * Poll a particular unit, looking for a particular scb
 1377  */
 1378 int
 1379 wds_ipoll(sc, scb, count)
 1380         struct wds_softc *sc;
 1381         struct wds_scb *scb;
 1382         int count;
 1383 {
 1384         bus_space_tag_t iot = sc->sc_iot;
 1385         bus_space_handle_t ioh = sc->sc_ioh;
 1386 
 1387         /* timeouts are in msec, so we loop in 1000 usec cycles */
 1388         while (count) {
 1389                 /*
 1390                  * If we had interrupts enabled, would we
 1391                  * have got an interrupt?
 1392                  */
 1393                 if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ)
 1394                         wdsintr(sc);
 1395                 if (scb->flags & SCB_DONE)
 1396                         return 0;
 1397                 delay(1000);    /* only happens in boot so ok */
 1398                 count--;
 1399         }
 1400         return 1;
 1401 }
 1402 
 1403 void
 1404 wds_timeout(arg)
 1405         void *arg;
 1406 {
 1407         struct wds_scb *scb = arg;
 1408         struct scsi_xfer *xs;
 1409         struct scsi_link *sc_link;
 1410         struct wds_softc *sc;
 1411         int s;
 1412 
 1413         s = splbio();
 1414 #ifdef notyet
 1415         isadma_copyfrombuf((caddr_t)scb, SCB_PHYS_SIZE, 1, scb->scb_phys);
 1416 #endif
 1417         xs = scb->xs;
 1418         sc_link = xs->sc_link;
 1419         sc = sc_link->adapter_softc;
 1420 
 1421         sc_print_addr(sc_link);
 1422         printf("timed out");
 1423 
 1424 #ifdef WDSDIAG
 1425         /*
 1426          * If The scb's mbx is not free, then the board has gone south?
 1427          */
 1428         wds_collect_mbo(sc);
 1429         if (scb->flags & SCB_SENDING) {
 1430                 printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
 1431                 Debugger();
 1432         }
 1433 #endif
 1434 
 1435         /*
 1436          * If it has been through before, then
 1437          * a previous abort has failed, don't
 1438          * try abort again
 1439          */
 1440         if (scb->flags & SCB_ABORT) {
 1441                 /* abort timed out */
 1442                 printf(" AGAIN\n");
 1443                 /* XXX Must reset! */
 1444         } else {
 1445                 /* abort the operation that has timed out */
 1446                 printf("\n");
 1447                 scb->xs->error = XS_TIMEOUT;
 1448                 scb->timeout = WDS_ABORT_TIMEOUT;
 1449                 scb->flags |= SCB_ABORT;
 1450                 wds_queue_scb(sc, scb);
 1451         }
 1452 
 1453         splx(s);
 1454 }

/* [<][>][^][v][top][bottom][index][help] */