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