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