1 /* $OpenBSD: wds.c,v 1.59 2022/04/16 19:19:59 naddy 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/param.h> 61 #include <sys/systm.h> 62 #include <sys/kernel.h> 63 #include <sys/errno.h> 64 #include <sys/ioctl.h> 65 #include <sys/device.h> 66 #include <sys/malloc.h> 67 #include <sys/buf.h> 68 #include <uvm/uvm_extern.h> 69 70 #include <machine/bus.h> 71 #include <machine/intr.h> 72 73 #include <scsi/scsi_all.h> 74 #include <scsi/scsiconf.h> 75 76 #include <dev/isa/isavar.h> 77 #include <dev/isa/isadmavar.h> 78 #include <dev/isa/wdsreg.h> 79 80 #define WDS_MBX_SIZE 16 81 82 #define WDS_SCB_MAX 32 83 #define SCB_HASH_SIZE 32 /* hash table size for phystokv */ 84 #define SCB_HASH_SHIFT 9 85 #define SCB_HASH(x) ((((long)(x))>>SCB_HASH_SHIFT) & (SCB_HASH_SIZE - 1)) 86 87 #define wds_nextmbx(wmb, mbx, mbio) \ 88 if ((wmb) == &(mbx)->mbio[WDS_MBX_SIZE - 1]) \ 89 (wmb) = &(mbx)->mbio[0]; \ 90 else \ 91 (wmb)++; 92 93 struct wds_mbx { 94 struct wds_mbx_out mbo[WDS_MBX_SIZE]; 95 struct wds_mbx_in mbi[WDS_MBX_SIZE]; 96 struct wds_mbx_out *cmbo; /* Collection Mail Box out */ 97 struct wds_mbx_out *tmbo; /* Target Mail Box out */ 98 struct wds_mbx_in *tmbi; /* Target Mail Box in */ 99 }; 100 101 #define KVTOPHYS(x) vtophys((vaddr_t)(x)) 102 103 struct wds_softc { 104 struct device sc_dev; 105 struct isadev sc_id; 106 void *sc_ih; 107 108 bus_space_tag_t sc_iot; /* bus identifier */ 109 bus_space_handle_t sc_ioh; /* io handle */ 110 int sc_irq, sc_drq; 111 112 int sc_revision; 113 114 struct wds_mbx sc_mbx; 115 #define wmbx (&sc->sc_mbx) 116 struct wds_scb *sc_scbhash[SCB_HASH_SIZE]; 117 TAILQ_HEAD(, wds_scb) sc_free_scb, sc_waiting_scb; 118 int sc_numscbs, sc_mbofull; 119 int sc_scsi_dev; 120 121 struct mutex sc_scb_mtx; 122 struct scsi_iopool sc_iopool; 123 }; 124 125 /* Define the bounce buffer length... */ 126 #define BUFLEN (64*1024) 127 /* ..and how many there are. One per device! Non-FASST boards need these. */ 128 #define BUFCNT 8 129 /* The macro for deciding whether the board needs a buffer. */ 130 #define NEEDBUFFER(sc) (sc->sc_revision < 0x800) 131 132 struct wds_buf { 133 u_char data[BUFLEN]; 134 int busy; 135 TAILQ_ENTRY(wds_buf) chain; 136 } wds_buffer[BUFCNT]; 137 138 TAILQ_HEAD(, wds_buf) wds_free_buffer; 139 140 #ifdef WDSDEBUG 141 int wds_debug = WDSDEBUG; 142 #endif 143 144 integrate void wds_wait(bus_space_tag_t, bus_space_handle_t, int, int, int); 145 int wds_cmd(struct wds_softc *, u_char *, int); 146 integrate void wds_finish_scbs(struct wds_softc *); 147 int wdsintr(void *); 148 integrate void wds_reset_scb(struct wds_softc *, struct wds_scb *); 149 void wds_scb_free(void *, void *); 150 void wds_free_buf(struct wds_softc *, struct wds_buf *); 151 integrate void wds_init_scb(struct wds_softc *, struct wds_scb *); 152 void *wds_scb_alloc(void *); 153 struct wds_buf *wds_get_buf(struct wds_softc *, int); 154 struct wds_scb *wds_scb_phys_kv(struct wds_softc *, u_long); 155 void wds_queue_scb(struct wds_softc *, struct wds_scb *); 156 void wds_collect_mbo(struct wds_softc *); 157 void wds_start_scbs(struct wds_softc *); 158 void wds_done(struct wds_softc *, struct wds_scb *, u_char); 159 int wds_find(struct isa_attach_args *, struct wds_softc *); 160 void wds_init(struct wds_softc *); 161 void wds_inquire_setup_information(struct wds_softc *); 162 void wds_scsi_cmd(struct scsi_xfer *); 163 void wds_sense(struct wds_softc *, struct wds_scb *); 164 int wds_poll(struct wds_softc *, struct scsi_xfer *, int); 165 int wds_ipoll(struct wds_softc *, struct wds_scb *, int); 166 void wds_timeout(void *); 167 int wdsprint(void *, const char *); 168 169 const struct scsi_adapter wds_switch = { 170 wds_scsi_cmd, NULL, NULL, NULL, NULL 171 }; 172 173 int wdsprobe(struct device *, void *, void *); 174 void wdsattach(struct device *, struct device *, void *); 175 176 const struct cfattach wds_ca = { 177 sizeof(struct wds_softc), wdsprobe, wdsattach 178 }; 179 180 struct cfdriver wds_cd = { 181 NULL, "wds", DV_DULL 182 }; 183 184 #define WDS_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */ 185 186 integrate void 187 wds_wait(bus_space_tag_t iot, bus_space_handle_t ioh, int port, int mask, 188 int val) 189 { 190 while ((bus_space_read_1(iot, ioh, port) & mask) != val) 191 ; 192 } 193 194 /* 195 * Write a command to the board's I/O ports. 196 */ 197 int 198 wds_cmd(struct wds_softc *sc, u_int8_t *ibuf, int icnt) 199 { 200 bus_space_tag_t iot = sc->sc_iot; 201 bus_space_handle_t ioh = sc->sc_ioh; 202 u_int8_t c; 203 204 wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY); 205 206 while (icnt--) { 207 bus_space_write_1(iot, ioh, WDS_CMD, *ibuf++); 208 wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY); 209 c = bus_space_read_1(iot, ioh, WDS_STAT); 210 if (c & WDSS_REJ) 211 return 1; 212 } 213 214 return 0; 215 } 216 217 /* 218 * Check for the presence of a WD7000 SCSI controller. 219 */ 220 int 221 wdsprobe(struct device *parent, void *match, void *aux) 222 { 223 register struct isa_attach_args *ia = aux; 224 bus_space_tag_t iot = ia->ia_iot; 225 bus_space_handle_t ioh; 226 int rv; 227 228 if (bus_space_map(iot, ia->ia_iobase, WDS_IO_PORTS, 0, &ioh)) 229 return (0); 230 231 /* See if there is a unit at this location. */ 232 rv = wds_find(ia, NULL); 233 234 bus_space_unmap(iot, ioh, WDS_IO_PORTS); 235 236 if (rv) { 237 ia->ia_msize = 0; 238 ia->ia_iosize = WDS_IO_PORTS; 239 } 240 241 return (rv); 242 } 243 244 int 245 wdsprint(void *aux, const char *name) 246 { 247 if (name != NULL) 248 printf("%s: scsibus ", name); 249 return UNCONF; 250 } 251 252 /* 253 * Attach all available units. 254 */ 255 void 256 wdsattach(struct device *parent, struct device *self, void *aux) 257 { 258 struct isa_attach_args *ia = aux; 259 struct wds_softc *sc = (void *)self; 260 struct scsibus_attach_args saa; 261 bus_space_tag_t iot = ia->ia_iot; 262 bus_space_handle_t ioh; 263 264 if (bus_space_map(iot, ia->ia_iobase, WDS_IO_PORTS, 0, &ioh)) { 265 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname); 266 return; 267 } 268 269 if (!wds_find(ia, sc)) 270 panic("wdsattach: wds_find of %s failed", self->dv_xname); 271 wds_init(sc); 272 273 if (sc->sc_drq != DRQUNK) 274 isadma_cascade(sc->sc_drq); 275 276 TAILQ_INIT(&sc->sc_free_scb); 277 TAILQ_INIT(&sc->sc_waiting_scb); 278 mtx_init(&sc->sc_scb_mtx, IPL_BIO); 279 scsi_iopool_init(&sc->sc_iopool, sc, wds_scb_alloc, wds_scb_free); 280 281 wds_inquire_setup_information(sc); 282 283 sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE, 284 IPL_BIO, wdsintr, sc, sc->sc_dev.dv_xname); 285 286 /* XXX */ 287 /* I don't think the -ASE can handle openings > 1. */ 288 /* It gives Vendor Error 26 whenever I try it. */ 289 saa.saa_adapter_softc = sc; 290 saa.saa_adapter_target = sc->sc_scsi_dev; 291 saa.saa_adapter = &wds_switch; 292 saa.saa_luns = saa.saa_adapter_buswidth = 8; 293 saa.saa_openings = 1; 294 saa.saa_pool = &sc->sc_iopool; 295 saa.saa_quirks = saa.saa_flags = 0; 296 saa.saa_wwpn = saa.saa_wwnn = 0; 297 298 config_found(self, &saa, wdsprint); 299 } 300 301 integrate void 302 wds_finish_scbs(struct wds_softc *sc) 303 { 304 struct wds_mbx_in *wmbi; 305 struct wds_scb *scb; 306 int i; 307 308 wmbi = wmbx->tmbi; 309 310 if (wmbi->stat == WDS_MBI_FREE) { 311 for (i = 0; i < WDS_MBX_SIZE; i++) { 312 if (wmbi->stat != WDS_MBI_FREE) { 313 printf("%s: mbi not in round-robin order\n", 314 sc->sc_dev.dv_xname); 315 goto AGAIN; 316 } 317 wds_nextmbx(wmbi, wmbx, mbi); 318 } 319 #ifdef WDSDIAGnot 320 printf("%s: mbi interrupt with no full mailboxes\n", 321 sc->sc_dev.dv_xname); 322 #endif 323 return; 324 } 325 326 AGAIN: 327 do { 328 scb = wds_scb_phys_kv(sc, phystol(wmbi->scb_addr)); 329 if (!scb) { 330 printf("%s: bad mbi scb pointer; skipping\n", 331 sc->sc_dev.dv_xname); 332 goto next; 333 } 334 335 #ifdef WDSDEBUG 336 if (wds_debug) { 337 u_int8_t *cp = (u_int8_t *)&scb->cmd.scb; 338 printf("op=%x %x %x %x %x %x\n", 339 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]); 340 printf("stat %x for mbi addr = %p, ", 341 wmbi->stat, wmbi); 342 printf("scb addr = %p\n", scb); 343 } 344 #endif /* WDSDEBUG */ 345 346 timeout_del(&scb->xs->stimeout); 347 wds_done(sc, scb, wmbi->stat); 348 349 next: 350 wmbi->stat = WDS_MBI_FREE; 351 wds_nextmbx(wmbi, wmbx, mbi); 352 } while (wmbi->stat != WDS_MBI_FREE); 353 354 wmbx->tmbi = wmbi; 355 } 356 357 /* 358 * Process an interrupt. 359 */ 360 int 361 wdsintr(void *arg) 362 { 363 struct wds_softc *sc = arg; 364 bus_space_tag_t iot = sc->sc_iot; 365 bus_space_handle_t ioh = sc->sc_ioh; 366 u_char c; 367 368 /* Was it really an interrupt from the board? */ 369 if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ) == 0) 370 return 0; 371 372 /* Get the interrupt status byte. */ 373 c = bus_space_read_1(iot, ioh, WDS_IRQSTAT) & WDSI_MASK; 374 375 /* Acknowledge (which resets) the interrupt. */ 376 bus_space_write_1(iot, ioh, WDS_IRQACK, 0x00); 377 378 switch (c) { 379 case WDSI_MSVC: 380 wds_finish_scbs(sc); 381 break; 382 383 case WDSI_MFREE: 384 wds_start_scbs(sc); 385 break; 386 387 default: 388 printf("%s: unrecognized interrupt type %02x", 389 sc->sc_dev.dv_xname, c); 390 break; 391 } 392 393 return 1; 394 } 395 396 integrate void 397 wds_reset_scb(struct wds_softc *sc, struct wds_scb *scb) 398 { 399 scb->flags = 0; 400 } 401 402 /* 403 * Free the command structure, the outgoing mailbox and the data buffer. 404 */ 405 void 406 wds_scb_free(void *xsc, void *xscb) 407 { 408 struct wds_softc *sc = xsc; 409 struct wds_scb *scb = xscb; 410 411 if (scb->buf) { 412 wds_free_buf(sc, scb->buf); 413 scb->buf = NULL; 414 } 415 416 wds_reset_scb(sc, scb); 417 mtx_enter(&sc->sc_scb_mtx); 418 TAILQ_INSERT_HEAD(&sc->sc_free_scb, scb, chain); 419 mtx_leave(&sc->sc_scb_mtx); 420 } 421 422 void 423 wds_free_buf(struct wds_softc *sc, struct wds_buf *buf) 424 { 425 int s; 426 427 s = splbio(); 428 429 buf->busy = 0; 430 TAILQ_INSERT_HEAD(&wds_free_buffer, buf, chain); 431 432 /* 433 * If there were none, wake anybody waiting for one to come free, 434 * starting with queued entries. 435 */ 436 if (TAILQ_NEXT(buf, chain) == NULL) 437 wakeup(&wds_free_buffer); 438 439 splx(s); 440 } 441 442 integrate void 443 wds_init_scb(struct wds_softc *sc, struct wds_scb *scb) 444 { 445 int hashnum; 446 447 bzero(scb, sizeof(struct wds_scb)); 448 /* 449 * put in the phystokv hash table 450 * Never gets taken out. 451 */ 452 scb->hashkey = KVTOPHYS(scb); 453 hashnum = SCB_HASH(scb->hashkey); 454 scb->nexthash = sc->sc_scbhash[hashnum]; 455 sc->sc_scbhash[hashnum] = scb; 456 wds_reset_scb(sc, scb); 457 } 458 459 /* 460 * Get a free scb 461 */ 462 void * 463 wds_scb_alloc(void *xsc) 464 { 465 struct wds_softc *sc = xsc; 466 struct wds_scb *scb; 467 468 mtx_enter(&sc->sc_scb_mtx); 469 scb = TAILQ_FIRST(&sc->sc_free_scb); 470 if (scb) { 471 TAILQ_REMOVE(&sc->sc_free_scb, scb, chain); 472 scb->flags |= SCB_ALLOC; 473 } 474 mtx_leave(&sc->sc_scb_mtx); 475 476 return (scb); 477 } 478 479 struct wds_buf * 480 wds_get_buf(struct wds_softc *sc, int flags) 481 { 482 struct wds_buf *buf; 483 int s; 484 485 s = splbio(); 486 487 for (;;) { 488 buf = TAILQ_FIRST(&wds_free_buffer); 489 if (buf) { 490 TAILQ_REMOVE(&wds_free_buffer, buf, chain); 491 break; 492 } 493 if ((flags & SCSI_NOSLEEP) != 0) 494 goto out; 495 tsleep_nsec(&wds_free_buffer, PRIBIO, "wdsbuf", INFSLP); 496 } 497 498 buf->busy = 1; 499 500 out: 501 splx(s); 502 return (buf); 503 } 504 505 struct wds_scb * 506 wds_scb_phys_kv(struct wds_softc *sc, u_long scb_phys) 507 { 508 int hashnum = SCB_HASH(scb_phys); 509 struct wds_scb *scb = sc->sc_scbhash[hashnum]; 510 511 while (scb) { 512 if (scb->hashkey == scb_phys) 513 break; 514 /* XXX Check to see if it matches the sense command block. */ 515 if (scb->hashkey == (scb_phys - sizeof(struct wds_cmd))) 516 break; 517 scb = scb->nexthash; 518 } 519 return scb; 520 } 521 522 /* 523 * Queue a SCB to be sent to the controller, and send it if possible. 524 */ 525 void 526 wds_queue_scb(struct wds_softc *sc, struct wds_scb *scb) 527 { 528 TAILQ_INSERT_TAIL(&sc->sc_waiting_scb, scb, chain); 529 wds_start_scbs(sc); 530 } 531 532 /* 533 * Garbage collect mailboxes that are no longer in use. 534 */ 535 void 536 wds_collect_mbo(struct wds_softc *sc) 537 { 538 struct wds_mbx_out *wmbo; /* Mail Box Out pointer */ 539 #ifdef WDSDIAG 540 struct wds_scb *scb; 541 #endif 542 543 wmbo = wmbx->cmbo; 544 545 while (sc->sc_mbofull > 0) { 546 if (wmbo->cmd != WDS_MBO_FREE) 547 break; 548 549 #ifdef WDSDIAG 550 scb = wds_scb_phys_kv(sc, phystol(wmbo->scb_addr)); 551 scb->flags &= ~SCB_SENDING; 552 #endif 553 554 --sc->sc_mbofull; 555 wds_nextmbx(wmbo, wmbx, mbo); 556 } 557 558 wmbx->cmbo = wmbo; 559 } 560 561 /* 562 * Send as many SCBs as we have empty mailboxes for. 563 */ 564 void 565 wds_start_scbs(struct wds_softc *sc) 566 { 567 struct wds_mbx_out *wmbo; /* Mail Box Out pointer */ 568 struct wds_scb *scb; 569 u_char c; 570 571 wmbo = wmbx->tmbo; 572 573 while ((scb = TAILQ_FIRST(&sc->sc_waiting_scb)) != NULL) { 574 if (sc->sc_mbofull >= WDS_MBX_SIZE) { 575 wds_collect_mbo(sc); 576 if (sc->sc_mbofull >= WDS_MBX_SIZE) { 577 c = WDSC_IRQMFREE; 578 wds_cmd(sc, &c, sizeof c); 579 break; 580 } 581 } 582 583 TAILQ_REMOVE(&sc->sc_waiting_scb, scb, chain); 584 #ifdef WDSDIAG 585 scb->flags |= SCB_SENDING; 586 #endif 587 timeout_set(&scb->xs->stimeout, wds_timeout, scb); 588 589 /* Link scb to mbo. */ 590 if (scb->flags & SCB_SENSE) 591 ltophys(KVTOPHYS(&scb->sense), wmbo->scb_addr); 592 else 593 ltophys(KVTOPHYS(&scb->cmd), wmbo->scb_addr); 594 /* XXX What about aborts? */ 595 wmbo->cmd = WDS_MBO_START; 596 597 /* Tell the card to poll immediately. */ 598 c = WDSC_MSTART(wmbo - wmbx->mbo); 599 wds_cmd(sc, &c, sizeof c); 600 601 if ((scb->flags & SCB_POLLED) == 0) 602 timeout_add_msec(&scb->xs->stimeout, scb->timeout); 603 604 ++sc->sc_mbofull; 605 wds_nextmbx(wmbo, wmbx, mbo); 606 } 607 608 wmbx->tmbo = wmbo; 609 } 610 611 /* 612 * Process the result of a SCSI command. 613 */ 614 void 615 wds_done(struct wds_softc *sc, struct wds_scb *scb, u_int8_t stat) 616 { 617 struct scsi_xfer *xs = scb->xs; 618 619 /* XXXXX */ 620 621 /* Don't release the SCB if it was an internal command. */ 622 if (xs == 0) { 623 scb->flags |= SCB_DONE; 624 return; 625 } 626 627 /* Sense handling. */ 628 if (xs->error == XS_SENSE) { 629 bcopy(&scb->sense_data, &xs->sense, sizeof (struct scsi_sense_data)); 630 } else { 631 if (xs->error == XS_NOERROR) { 632 /* If all went well, or an error is acceptable. */ 633 if (stat == WDS_MBI_OK) { 634 /* OK, set the result */ 635 xs->resid = 0; 636 } else { 637 /* Check the mailbox status. */ 638 switch (stat) { 639 case WDS_MBI_OKERR: 640 /* SCSI error recorded in scb, counts as WDS_MBI_OK */ 641 switch (scb->cmd.venderr) { 642 case 0x00: 643 printf("%s: Is this an error?\n", sc->sc_dev.dv_xname); 644 xs->error = XS_DRIVER_STUFFUP; /* Experiment */ 645 break; 646 case 0x01: 647 /*printf("%s: OK, see SCSI error field.\n", sc->sc_dev.dv_xname);*/ 648 if (scb->cmd.stat == SCSI_CHECK) { 649 /* Do sense. */ 650 wds_sense (sc, scb); 651 return; 652 } else if (scb->cmd.stat == SCSI_BUSY) { 653 xs->error = XS_BUSY; 654 } 655 break; 656 case 0x40: 657 /*printf("%s: DMA underrun!\n", sc->sc_dev.dv_xname);*/ 658 /* Hits this if the target returns fewer that datalen bytes (eg my CD-ROM, 659 which returns a short version string, or if DMA is turned off etc. */ 660 xs->resid = 0; 661 break; 662 default: 663 printf("%s: VENDOR ERROR %02x, scsi %02x\n", sc->sc_dev.dv_xname, scb->cmd.venderr, scb->cmd.stat); 664 xs->error = XS_DRIVER_STUFFUP; /* Experiment */ 665 break; 666 } 667 break; 668 case WDS_MBI_ETIME: 669 /* 670 * The documentation isn't clear on 671 * what conditions might generate this, 672 * but selection timeouts are the only 673 * one I can think of. 674 */ 675 xs->error = XS_SELTIMEOUT; 676 break; 677 case WDS_MBI_ERESET: 678 case WDS_MBI_ETARCMD: 679 case WDS_MBI_ERESEL: 680 case WDS_MBI_ESEL: 681 case WDS_MBI_EABORT: 682 case WDS_MBI_ESRESET: 683 case WDS_MBI_EHRESET: 684 xs->error = XS_DRIVER_STUFFUP; 685 break; 686 } 687 } 688 } /* else sense */ 689 690 if (NEEDBUFFER(sc) && xs->datalen) { 691 if (xs->flags & SCSI_DATA_IN) 692 bcopy(scb->buf->data, xs->data, xs->datalen); 693 } 694 } /* XS_NOERROR */ 695 696 scsi_done(xs); 697 } 698 699 int 700 wds_find(struct isa_attach_args *ia, struct wds_softc *sc) 701 { 702 bus_space_tag_t iot = ia->ia_iot; 703 bus_space_handle_t ioh = ia->ia_ioh; 704 u_char c; 705 int i; 706 707 /* 708 * Sending a command causes the CMDRDY bit to clear. 709 */ 710 c = bus_space_read_1(iot, ioh, WDS_STAT); 711 for (i = 0; i < 4; i++) { 712 if ((bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_RDY) != 0) 713 goto ready; 714 delay(10); 715 } 716 return (0); 717 718 ready: 719 bus_space_write_1(iot, ioh, WDS_CMD, WDSC_NOOP); 720 if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_RDY) 721 return (0); 722 723 bus_space_write_1(iot, ioh, WDS_HCR, WDSH_SCSIRESET|WDSH_ASCRESET); 724 delay(10000); 725 bus_space_write_1(iot, ioh, WDS_HCR, 0x00); 726 delay(500000); 727 wds_wait(iot, ioh, WDS_STAT, WDSS_RDY, WDSS_RDY); 728 if (bus_space_read_1(iot, ioh, WDS_IRQSTAT) != 1) 729 if (bus_space_read_1(iot, ioh, WDS_IRQSTAT) != 7) 730 printf("%s: failed reset!!! %2x\n", 731 sc ? sc->sc_dev.dv_xname : "wds?", 732 bus_space_read_1(iot, ioh, WDS_IRQSTAT)); 733 734 if ((bus_space_read_1(iot, ioh, WDS_STAT) & (WDSS_RDY)) != WDSS_RDY) { 735 printf("%s: waiting for controller to become ready.", 736 sc ? sc->sc_dev.dv_xname : "wds?"); 737 for (i = 0; i < 20; i++) { 738 if ((bus_space_read_1(iot, ioh, WDS_STAT) & 739 (WDSS_RDY)) == WDSS_RDY) 740 break; 741 printf("."); 742 delay(10000); 743 } 744 if ((bus_space_read_1(iot, ioh, WDS_STAT) & (WDSS_RDY)) != 745 WDSS_RDY) { 746 printf(" failed\n"); 747 return (0); 748 } 749 printf("\n"); 750 } 751 752 if (sc != NULL) { 753 /* XXX Can we do this better? */ 754 /* who are we on the scsi bus? */ 755 sc->sc_scsi_dev = 7; 756 757 sc->sc_iot = iot; 758 sc->sc_ioh = ioh; 759 sc->sc_irq = ia->ia_irq; 760 sc->sc_drq = ia->ia_drq; 761 } 762 763 return (1); 764 } 765 766 /* 767 * Initialise the board and driver. 768 */ 769 void 770 wds_init(struct wds_softc *sc) 771 { 772 bus_space_tag_t iot = sc->sc_iot; 773 bus_space_handle_t ioh = sc->sc_ioh; 774 struct wds_setup init; 775 u_char c; 776 int i; 777 778 /* 779 * Set up initial mail box for round-robin operation. 780 */ 781 for (i = 0; i < WDS_MBX_SIZE; i++) { 782 wmbx->mbo[i].cmd = WDS_MBO_FREE; 783 wmbx->mbi[i].stat = WDS_MBI_FREE; 784 } 785 wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0]; 786 wmbx->tmbi = &wmbx->mbi[0]; 787 sc->sc_mbofull = 0; 788 789 /* Clear the buffers. */ 790 TAILQ_INIT(&wds_free_buffer); 791 for (i = 0; i < BUFCNT; i++) { 792 wds_buffer[i].busy = 0; 793 TAILQ_INSERT_HEAD(&wds_free_buffer, &wds_buffer[i], chain); 794 } 795 796 init.opcode = WDSC_INIT; 797 init.scsi_id = sc->sc_scsi_dev; 798 /* Record scsi id of controller for use in scsi_attach */ 799 sc->sc_scsi_dev = init.scsi_id; 800 init.buson_t = 48; 801 init.busoff_t = 24; 802 init.xx = 0; 803 ltophys(KVTOPHYS(wmbx), init.mbaddr); 804 init.nomb = init.nimb = WDS_MBX_SIZE; 805 wds_cmd(sc, (u_char *)&init, sizeof init); 806 807 wds_wait(iot, ioh, WDS_STAT, WDSS_INIT, WDSS_INIT); 808 809 c = WDSC_DISUNSOL; 810 wds_cmd(sc, &c, sizeof c); 811 812 bus_space_write_1(iot, ioh, WDS_HCR, WDSH_DRQEN); 813 } 814 815 /* 816 * Read the board's firmware revision information. 817 */ 818 void 819 wds_inquire_setup_information(struct wds_softc *sc) 820 { 821 struct wds_scb *scb; 822 u_char *j; 823 int s; 824 825 scb = scsi_io_get(&sc->sc_iopool, SCSI_NOSLEEP); 826 if (scb == NULL) { 827 printf("%s: no request slot available in getvers()!\n", 828 sc->sc_dev.dv_xname); 829 return; 830 } 831 scb->xs = NULL; 832 scb->timeout = 40; 833 834 bzero(&scb->cmd, sizeof scb->cmd); 835 scb->cmd.write = 0x80; 836 scb->cmd.opcode = WDSX_GETFIRMREV; 837 838 /* Will poll card, await result. */ 839 bus_space_write_1(sc->sc_iot, sc->sc_ioh, WDS_HCR, WDSH_DRQEN); 840 scb->flags |= SCB_POLLED; 841 842 s = splbio(); 843 wds_queue_scb(sc, scb); 844 splx(s); 845 846 if (wds_ipoll(sc, scb, scb->timeout)) 847 goto out; 848 849 /* Print the version number. */ 850 printf(": version %x.%02x ", scb->cmd.targ, scb->cmd.scb.opcode); 851 sc->sc_revision = (scb->cmd.targ << 8) | scb->cmd.scb.opcode; 852 /* Print out the version string. */ 853 j = 2 + &(scb->cmd.targ); 854 while ((*j >= 32) && (*j < 128)) { 855 printf("%c", *j); 856 j++; 857 } 858 859 out: 860 printf("\n"); 861 scsi_io_put(&sc->sc_iopool, scb); 862 } 863 864 /* 865 * Send a SCSI command. 866 */ 867 void 868 wds_scsi_cmd(struct scsi_xfer *xs) 869 { 870 struct scsi_link *sc_link = xs->sc_link; 871 struct wds_softc *sc = sc_link->bus->sb_adapter_softc; 872 bus_space_tag_t iot = sc->sc_iot; 873 bus_space_handle_t ioh = sc->sc_ioh; 874 struct wds_scb *scb; 875 struct wds_scat_gath *sg; 876 int seg; 877 u_long thiskv, thisphys, nextphys; 878 int bytes_this_seg, bytes_this_page, datalen, flags; 879 int s; 880 881 if (xs->flags & SCSI_RESET) { 882 /* XXX Fix me! */ 883 printf("%s: reset!\n", sc->sc_dev.dv_xname); 884 wds_init(sc); 885 scsi_done(xs); 886 return; 887 } 888 889 flags = xs->flags; 890 scb = xs->io; 891 scb->xs = xs; 892 scb->timeout = xs->timeout; 893 894 /* Zero out the command structure. */ 895 bzero(&scb->cmd, sizeof scb->cmd); 896 bcopy(&xs->cmd, &scb->cmd.scb, xs->cmdlen < 12 ? xs->cmdlen : 12); 897 898 /* Set up some of the command fields. */ 899 scb->cmd.targ = (xs->sc_link->target << 5) | xs->sc_link->lun; 900 901 /* NOTE: cmd.write may be OK as 0x40 (disable direction checking) 902 * on boards other than the WD-7000V-ASE. Need this for the ASE: 903 */ 904 scb->cmd.write = (xs->flags & SCSI_DATA_IN) ? 0x80 : 0x00; 905 906 if (!NEEDBUFFER(sc) && xs->datalen) { 907 sg = scb->scat_gath; 908 seg = 0; 909 910 /* 911 * Set up the scatter-gather block. 912 */ 913 #ifdef WDSDEBUG 914 printf("%s: %d @%p:- ", sc->sc_dev.dv_xname, xs->datalen, xs->data); 915 #endif 916 917 datalen = xs->datalen; 918 thiskv = (int)xs->data; 919 thisphys = KVTOPHYS(xs->data); 920 921 while (datalen && seg < WDS_NSEG) { 922 bytes_this_seg = 0; 923 924 /* put in the base address */ 925 ltophys(thisphys, sg->seg_addr); 926 927 #ifdef WDSDEBUG 928 printf("0x%lx", thisphys); 929 #endif 930 931 /* do it at least once */ 932 nextphys = thisphys; 933 while (datalen && thisphys == nextphys) { 934 /* 935 * This page is contiguous (physically) 936 * with the last, just extend the 937 * length 938 */ 939 /* check it fits on the ISA bus */ 940 if (thisphys > 0xFFFFFF) { 941 printf("%s: DMA beyond" 942 " end of ISA\n", 943 sc->sc_dev.dv_xname); 944 goto bad; 945 } 946 /* how far to the end of the page */ 947 nextphys = (thisphys & ~PGOFSET) + NBPG; 948 bytes_this_page = nextphys - thisphys; 949 /**** or the data ****/ 950 bytes_this_page = min(bytes_this_page, 951 datalen); 952 bytes_this_seg += bytes_this_page; 953 datalen -= bytes_this_page; 954 955 /* get more ready for the next page */ 956 thiskv = (thiskv & ~PGOFSET) + NBPG; 957 if (datalen) 958 thisphys = KVTOPHYS(thiskv); 959 } 960 /* 961 * next page isn't contiguous, finish the seg 962 */ 963 #ifdef WDSDEBUG 964 printf("(0x%x)", bytes_this_seg); 965 #endif 966 ltophys(bytes_this_seg, sg->seg_len); 967 sg++; 968 seg++; 969 } 970 971 #ifdef WDSDEBUG 972 printf("\n"); 973 #endif 974 if (datalen) { 975 /* 976 * there's still data, must have run out of segs! 977 */ 978 printf("%s: wds_scsi_cmd, more than %d dma segs\n", 979 sc->sc_dev.dv_xname, WDS_NSEG); 980 goto bad; 981 } 982 scb->cmd.opcode = WDSX_SCSISG; 983 ltophys(KVTOPHYS(scb->scat_gath), scb->cmd.data); 984 ltophys(seg * sizeof(struct wds_scat_gath), scb->cmd.len); 985 } else if (xs->datalen > 0) { 986 /* The board is an ASC or ASE. Do not use scatter/gather. */ 987 if (xs->datalen > BUFLEN) { 988 printf("%s: wds_scsi_cmd, I/O too large for bounce buffer\n", 989 sc->sc_dev.dv_xname); 990 goto bad; 991 } 992 if (xs->flags & SCSI_DATA_OUT) 993 bcopy(xs->data, scb->buf->data, xs->datalen); 994 else 995 bzero(scb->buf->data, xs->datalen); 996 scb->cmd.opcode = WDSX_SCSICMD; 997 ltophys(KVTOPHYS(scb->buf->data), scb->cmd.data); 998 ltophys(xs->datalen, scb->cmd.len); 999 } else { 1000 scb->cmd.opcode = WDSX_SCSICMD; 1001 ltophys(0, scb->cmd.data); 1002 ltophys(0, scb->cmd.len); 1003 } 1004 1005 scb->cmd.stat = 0x00; 1006 scb->cmd.venderr = 0x00; 1007 ltophys(0, scb->cmd.link); 1008 1009 /* XXX Do we really want to do this? */ 1010 if (flags & SCSI_POLL) { 1011 /* Will poll card, await result. */ 1012 bus_space_write_1(iot, ioh, WDS_HCR, WDSH_DRQEN); 1013 scb->flags |= SCB_POLLED; 1014 } else { 1015 /* Will send command, let interrupt routine handle result. */ 1016 bus_space_write_1(iot, ioh, WDS_HCR, WDSH_IRQEN | WDSH_DRQEN); 1017 } 1018 1019 s = splbio(); 1020 wds_queue_scb(sc, scb); 1021 1022 splx(s); 1023 1024 if ((flags & SCSI_POLL) == 0) 1025 return; 1026 1027 if (wds_poll(sc, xs, scb->timeout)) { 1028 wds_timeout(scb); 1029 if (wds_poll(sc, xs, scb->timeout)) 1030 wds_timeout(scb); 1031 } 1032 return; 1033 1034 bad: 1035 xs->error = XS_DRIVER_STUFFUP; 1036 } 1037 1038 /* 1039 * Send a sense request. 1040 */ 1041 void 1042 wds_sense(struct wds_softc *sc, struct wds_scb *scb) 1043 { 1044 struct scsi_xfer *xs = scb->xs; 1045 struct scsi_sense *ss = (void *)&scb->sense.scb; 1046 int s; 1047 1048 /* XXXXX */ 1049 1050 /* Send sense request SCSI command. */ 1051 xs->error = XS_SENSE; 1052 scb->flags |= SCB_SENSE; 1053 1054 /* First, save the return values */ 1055 if (NEEDBUFFER(sc) && xs->datalen) { 1056 if (xs->flags & SCSI_DATA_IN) 1057 bcopy(scb->buf->data, xs->data, xs->datalen); 1058 } 1059 1060 /* Next, setup a request sense command block */ 1061 bzero(ss, sizeof(*ss)); 1062 ss->opcode = REQUEST_SENSE; 1063 ss->byte2 = xs->sc_link->lun << 5; 1064 ss->length = sizeof(struct scsi_sense_data); 1065 1066 /* Set up some of the command fields. */ 1067 scb->sense.targ = scb->cmd.targ; 1068 scb->sense.write = 0x80; 1069 scb->sense.opcode = WDSX_SCSICMD; 1070 ltophys(KVTOPHYS(&scb->sense_data), scb->sense.data); 1071 ltophys(sizeof(struct scsi_sense_data), scb->sense.len); 1072 1073 s = splbio(); 1074 wds_queue_scb(sc, scb); 1075 splx(s); 1076 1077 /* 1078 * There's no reason for us to poll here. There are two cases: 1079 * 1) If it's a polling operation, then we're called from the interrupt 1080 * handler, and we return and continue polling. 1081 * 2) If it's an interrupt-driven operation, then it gets completed 1082 * later on when the REQUEST SENSE finishes. 1083 */ 1084 } 1085 1086 /* 1087 * Poll a particular unit, looking for a particular scb 1088 */ 1089 int 1090 wds_poll(struct wds_softc *sc, struct scsi_xfer *xs, int count) 1091 { 1092 bus_space_tag_t iot = sc->sc_iot; 1093 bus_space_handle_t ioh = sc->sc_ioh; 1094 int s; 1095 1096 /* timeouts are in msec, so we loop in 1000 usec cycles */ 1097 while (count) { 1098 /* 1099 * If we had interrupts enabled, would we 1100 * have got an interrupt? 1101 */ 1102 if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ) { 1103 s = splbio(); 1104 wdsintr(sc); 1105 splx(s); 1106 } 1107 if (xs->flags & ITSDONE) 1108 return 0; 1109 delay(1000); /* only happens in boot so ok */ 1110 count--; 1111 } 1112 return 1; 1113 } 1114 1115 /* 1116 * Poll a particular unit, looking for a particular scb 1117 */ 1118 int 1119 wds_ipoll(struct wds_softc *sc, struct wds_scb *scb, int count) 1120 { 1121 bus_space_tag_t iot = sc->sc_iot; 1122 bus_space_handle_t ioh = sc->sc_ioh; 1123 int s; 1124 1125 /* timeouts are in msec, so we loop in 1000 usec cycles */ 1126 while (count) { 1127 /* 1128 * If we had interrupts enabled, would we 1129 * have got an interrupt? 1130 */ 1131 if (bus_space_read_1(iot, ioh, WDS_STAT) & WDSS_IRQ) { 1132 s = splbio(); 1133 wdsintr(sc); 1134 splx(s); 1135 } 1136 if (scb->flags & SCB_DONE) 1137 return 0; 1138 delay(1000); /* only happens in boot so ok */ 1139 count--; 1140 } 1141 return 1; 1142 } 1143 1144 void 1145 wds_timeout(void *arg) 1146 { 1147 struct wds_scb *scb = arg; 1148 struct scsi_xfer *xs; 1149 struct scsi_link *sc_link; 1150 struct wds_softc *sc; 1151 int s; 1152 1153 s = splbio(); 1154 xs = scb->xs; 1155 sc_link = xs->sc_link; 1156 sc = sc_link->bus->sb_adapter_softc; 1157 1158 sc_print_addr(sc_link); 1159 printf("timed out"); 1160 1161 #ifdef WDSDIAG 1162 /* 1163 * If The scb's mbx is not free, then the board has gone south? 1164 */ 1165 wds_collect_mbo(sc); 1166 if (scb->flags & SCB_SENDING) 1167 panic("%s: not taking commands!", sc->sc_dev.dv_xname); 1168 #endif 1169 1170 /* 1171 * If it has been through before, then 1172 * a previous abort has failed, don't 1173 * try abort again 1174 */ 1175 if (scb->flags & SCB_ABORT) { 1176 /* abort timed out */ 1177 printf(" AGAIN\n"); 1178 /* XXX Must reset! */ 1179 } else { 1180 /* abort the operation that has timed out */ 1181 printf("\n"); 1182 scb->xs->error = XS_TIMEOUT; 1183 scb->timeout = WDS_ABORT_TIMEOUT; 1184 scb->flags |= SCB_ABORT; 1185 wds_queue_scb(sc, scb); 1186 } 1187 1188 splx(s); 1189 } 1190