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