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