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