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