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