1 /* $NetBSD: ahb.c,v 1.35 2002/04/05 18:27:48 bouyer Exp $ */ 2 3 /*- 4 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace 9 * Simulation Facility, NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Originally written by Julian Elischer (julian@tfs.com) 42 * for TRW Financial Systems for use under the MACH(2.5) operating system. 43 * 44 * TRW Financial Systems, in accordance with their agreement with Carnegie 45 * Mellon University, makes this software available to CMU to distribute 46 * or use in any manner that they see fit as long as this message is kept with 47 * the software. For this reason TFS also grants any other persons or 48 * organisations permission to use or modify this software. 49 * 50 * TFS supplies this software to be publicly redistributed 51 * on the understanding that TFS is not responsible for the correct 52 * functioning of this software in any circumstances. 53 */ 54 55 #include <sys/cdefs.h> 56 __KERNEL_RCSID(0, "$NetBSD: ahb.c,v 1.35 2002/04/05 18:27:48 bouyer Exp $"); 57 58 #include "opt_ddb.h" 59 60 #undef AHBDEBUG 61 #ifdef DDB 62 #define integrate 63 #else 64 #define integrate static inline 65 #endif 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/kernel.h> 70 #include <sys/errno.h> 71 #include <sys/ioctl.h> 72 #include <sys/device.h> 73 #include <sys/malloc.h> 74 #include <sys/buf.h> 75 #include <sys/proc.h> 76 #include <sys/user.h> 77 78 #include <uvm/uvm_extern.h> 79 80 #include <machine/bus.h> 81 #include <machine/intr.h> 82 83 #include <dev/scsipi/scsi_all.h> 84 #include <dev/scsipi/scsipi_all.h> 85 #include <dev/scsipi/scsiconf.h> 86 87 #include <dev/eisa/eisareg.h> 88 #include <dev/eisa/eisavar.h> 89 #include <dev/eisa/eisadevs.h> 90 #include <dev/eisa/ahbreg.h> 91 92 #ifndef DDB 93 #define Debugger() panic("should call debugger here (aha1742.c)") 94 #endif /* ! DDB */ 95 96 #define AHB_ECB_MAX 32 /* store up to 32 ECBs at one time */ 97 #define ECB_HASH_SIZE 32 /* hash table size for phystokv */ 98 #define ECB_HASH_SHIFT 9 99 #define ECB_HASH(x) ((((long)(x))>>ECB_HASH_SHIFT) & (ECB_HASH_SIZE - 1)) 100 101 #define AHB_MAXXFER ((AHB_NSEG - 1) << PGSHIFT) 102 103 struct ahb_softc { 104 struct device sc_dev; 105 106 bus_space_tag_t sc_iot; 107 bus_space_handle_t sc_ioh; 108 bus_dma_tag_t sc_dmat; 109 void *sc_ih; 110 111 bus_dmamap_t sc_dmamap_ecb; /* maps the ecbs */ 112 struct ahb_ecb *sc_ecbs; /* all our ecbs */ 113 114 struct ahb_ecb *sc_ecbhash[ECB_HASH_SIZE]; 115 TAILQ_HEAD(, ahb_ecb) sc_free_ecb; 116 struct ahb_ecb *sc_immed_ecb; /* an outstanding immediete command */ 117 int sc_numecbs; 118 119 struct scsipi_adapter sc_adapter; 120 struct scsipi_channel sc_channel; 121 }; 122 123 /* 124 * Offset of an ECB from the beginning of the ECB DMA mapping. 125 */ 126 #define AHB_ECB_OFF(e) (((u_long)(e)) - ((u_long)&sc->sc_ecbs[0])) 127 128 struct ahb_probe_data { 129 int sc_irq; 130 int sc_scsi_dev; 131 }; 132 133 void ahb_send_mbox __P((struct ahb_softc *, int, struct ahb_ecb *)); 134 void ahb_send_immed __P((struct ahb_softc *, u_int32_t, struct ahb_ecb *)); 135 int ahbintr __P((void *)); 136 void ahb_free_ecb __P((struct ahb_softc *, struct ahb_ecb *)); 137 struct ahb_ecb *ahb_get_ecb __P((struct ahb_softc *)); 138 struct ahb_ecb *ahb_ecb_phys_kv __P((struct ahb_softc *, physaddr)); 139 void ahb_done __P((struct ahb_softc *, struct ahb_ecb *)); 140 int ahb_find __P((bus_space_tag_t, bus_space_handle_t, struct ahb_probe_data *)); 141 int ahb_init __P((struct ahb_softc *)); 142 void ahbminphys __P((struct buf *)); 143 void ahb_scsipi_request __P((struct scsipi_channel *, 144 scsipi_adapter_req_t, void *)); 145 int ahb_poll __P((struct ahb_softc *, struct scsipi_xfer *, int)); 146 void ahb_timeout __P((void *)); 147 int ahb_create_ecbs __P((struct ahb_softc *, struct ahb_ecb *, int)); 148 149 integrate void ahb_reset_ecb __P((struct ahb_softc *, struct ahb_ecb *)); 150 integrate int ahb_init_ecb __P((struct ahb_softc *, struct ahb_ecb *)); 151 152 int ahbmatch __P((struct device *, struct cfdata *, void *)); 153 void ahbattach __P((struct device *, struct device *, void *)); 154 155 struct cfattach ahb_ca = { 156 sizeof(struct ahb_softc), ahbmatch, ahbattach 157 }; 158 159 #define AHB_ABORT_TIMEOUT 2000 /* time to wait for abort (mSec) */ 160 161 /* 162 * Check the slots looking for a board we recognise 163 * If we find one, note it's address (slot) and call 164 * the actual probe routine to check it out. 165 */ 166 int 167 ahbmatch(parent, match, aux) 168 struct device *parent; 169 struct cfdata *match; 170 void *aux; 171 { 172 struct eisa_attach_args *ea = aux; 173 bus_space_tag_t iot = ea->ea_iot; 174 bus_space_handle_t ioh; 175 int rv; 176 177 /* must match one of our known ID strings */ 178 if (strcmp(ea->ea_idstring, "ADP0000") && 179 strcmp(ea->ea_idstring, "ADP0001") && 180 strcmp(ea->ea_idstring, "ADP0002") && 181 strcmp(ea->ea_idstring, "ADP0400")) 182 return (0); 183 184 if (bus_space_map(iot, 185 EISA_SLOT_ADDR(ea->ea_slot) + AHB_EISA_SLOT_OFFSET, AHB_EISA_IOSIZE, 186 0, &ioh)) 187 return (0); 188 189 rv = !ahb_find(iot, ioh, NULL); 190 191 bus_space_unmap(iot, ioh, AHB_EISA_IOSIZE); 192 193 return (rv); 194 } 195 196 /* 197 * Attach all the sub-devices we can find 198 */ 199 void 200 ahbattach(parent, self, aux) 201 struct device *parent, *self; 202 void *aux; 203 { 204 struct eisa_attach_args *ea = aux; 205 struct ahb_softc *sc = (void *)self; 206 bus_space_tag_t iot = ea->ea_iot; 207 bus_space_handle_t ioh; 208 eisa_chipset_tag_t ec = ea->ea_ec; 209 eisa_intr_handle_t ih; 210 const char *model, *intrstr; 211 struct ahb_probe_data apd; 212 struct scsipi_adapter *adapt = &sc->sc_adapter; 213 struct scsipi_channel *chan = &sc->sc_channel; 214 215 if (!strcmp(ea->ea_idstring, "ADP0000")) 216 model = EISA_PRODUCT_ADP0000; 217 else if (!strcmp(ea->ea_idstring, "ADP0001")) 218 model = EISA_PRODUCT_ADP0001; 219 else if (!strcmp(ea->ea_idstring, "ADP0002")) 220 model = EISA_PRODUCT_ADP0002; 221 else if (!strcmp(ea->ea_idstring, "ADP0400")) 222 model = EISA_PRODUCT_ADP0400; 223 else 224 model = "unknown model!"; 225 printf(": %s\n", model); 226 227 if (bus_space_map(iot, 228 EISA_SLOT_ADDR(ea->ea_slot) + AHB_EISA_SLOT_OFFSET, AHB_EISA_IOSIZE, 229 0, &ioh)) 230 panic("ahbattach: could not map I/O addresses"); 231 232 sc->sc_iot = iot; 233 sc->sc_ioh = ioh; 234 sc->sc_dmat = ea->ea_dmat; 235 if (ahb_find(iot, ioh, &apd)) 236 panic("ahbattach: ahb_find failed!"); 237 238 TAILQ_INIT(&sc->sc_free_ecb); 239 240 /* 241 * Fill in the scsipi_adapter. 242 */ 243 memset(adapt, 0, sizeof(*adapt)); 244 adapt->adapt_dev = &sc->sc_dev; 245 adapt->adapt_nchannels = 1; 246 /* adapt_openings initialized below */ 247 adapt->adapt_max_periph = 4; /* XXX arbitrary? */ 248 adapt->adapt_request = ahb_scsipi_request; 249 adapt->adapt_minphys = ahbminphys; 250 251 /* 252 * Fill in the scsipi_channel. 253 */ 254 memset(chan, 0, sizeof(*chan)); 255 chan->chan_adapter = adapt; 256 chan->chan_bustype = &scsi_bustype; 257 chan->chan_channel = 0; 258 chan->chan_ntargets = 8; 259 chan->chan_nluns = 8; 260 chan->chan_id = apd.sc_scsi_dev; 261 262 if (ahb_init(sc) != 0) { 263 /* Error during initialization! */ 264 return; 265 } 266 267 if (eisa_intr_map(ec, apd.sc_irq, &ih)) { 268 printf("%s: couldn't map interrupt (%d)\n", 269 sc->sc_dev.dv_xname, apd.sc_irq); 270 return; 271 } 272 intrstr = eisa_intr_string(ec, ih); 273 sc->sc_ih = eisa_intr_establish(ec, ih, IST_LEVEL, IPL_BIO, 274 ahbintr, sc); 275 if (sc->sc_ih == NULL) { 276 printf("%s: couldn't establish interrupt", 277 sc->sc_dev.dv_xname); 278 if (intrstr != NULL) 279 printf(" at %s", intrstr); 280 printf("\n"); 281 return; 282 } 283 if (intrstr != NULL) 284 printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, 285 intrstr); 286 287 /* 288 * ask the adapter what subunits are present 289 */ 290 config_found(self, &sc->sc_channel, scsiprint); 291 } 292 293 /* 294 * Function to send a command out through a mailbox 295 */ 296 void 297 ahb_send_mbox(sc, opcode, ecb) 298 struct ahb_softc *sc; 299 int opcode; 300 struct ahb_ecb *ecb; 301 { 302 bus_space_tag_t iot = sc->sc_iot; 303 bus_space_handle_t ioh = sc->sc_ioh; 304 int wait = 300; /* 1ms should be enough */ 305 306 while (--wait) { 307 if ((bus_space_read_1(iot, ioh, G2STAT) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY)) 308 == (G2STAT_MBOX_EMPTY)) 309 break; 310 delay(10); 311 } 312 if (!wait) { 313 printf("%s: board not responding\n", sc->sc_dev.dv_xname); 314 Debugger(); 315 } 316 317 /* 318 * don't know if this will work. 319 * XXX WHAT DOES THIS COMMENT MEAN?! --thorpej 320 */ 321 bus_space_write_4(iot, ioh, MBOXOUT0, 322 sc->sc_dmamap_ecb->dm_segs[0].ds_addr + AHB_ECB_OFF(ecb)); 323 bus_space_write_1(iot, ioh, ATTN, opcode | 324 ecb->xs->xs_periph->periph_target); 325 326 if ((ecb->xs->xs_control & XS_CTL_POLL) == 0) 327 callout_reset(&ecb->xs->xs_callout, 328 mstohz(ecb->timeout), ahb_timeout, ecb); 329 } 330 331 /* 332 * Function to send an immediate type command to the adapter 333 */ 334 void 335 ahb_send_immed(sc, cmd, ecb) 336 struct ahb_softc *sc; 337 u_int32_t cmd; 338 struct ahb_ecb *ecb; 339 { 340 bus_space_tag_t iot = sc->sc_iot; 341 bus_space_handle_t ioh = sc->sc_ioh; 342 int wait = 100; /* 1 ms enough? */ 343 344 while (--wait) { 345 if ((bus_space_read_1(iot, ioh, G2STAT) & (G2STAT_BUSY | G2STAT_MBOX_EMPTY)) 346 == (G2STAT_MBOX_EMPTY)) 347 break; 348 delay(10); 349 } 350 if (!wait) { 351 printf("%s: board not responding\n", sc->sc_dev.dv_xname); 352 Debugger(); 353 } 354 355 bus_space_write_4(iot, ioh, MBOXOUT0, cmd); /* don't know this will work */ 356 bus_space_write_1(iot, ioh, G2CNTRL, G2CNTRL_SET_HOST_READY); 357 bus_space_write_1(iot, ioh, ATTN, OP_IMMED | 358 ecb->xs->xs_periph->periph_target); 359 360 if ((ecb->xs->xs_control & XS_CTL_POLL) == 0) 361 callout_reset(&ecb->xs->xs_callout, 362 mstohz(ecb->timeout), ahb_timeout, ecb); 363 } 364 365 /* 366 * Catch an interrupt from the adaptor 367 */ 368 int 369 ahbintr(arg) 370 void *arg; 371 { 372 struct ahb_softc *sc = arg; 373 bus_space_tag_t iot = sc->sc_iot; 374 bus_space_handle_t ioh = sc->sc_ioh; 375 struct ahb_ecb *ecb; 376 u_char ahbstat; 377 u_int32_t mboxval; 378 379 #ifdef AHBDEBUG 380 printf("%s: ahbintr ", sc->sc_dev.dv_xname); 381 #endif /* AHBDEBUG */ 382 383 if ((bus_space_read_1(iot, ioh, G2STAT) & G2STAT_INT_PEND) == 0) 384 return 0; 385 386 for (;;) { 387 /* 388 * First get all the information and then 389 * acknowlege the interrupt 390 */ 391 ahbstat = bus_space_read_1(iot, ioh, G2INTST); 392 mboxval = bus_space_read_4(iot, ioh, MBOXIN0); 393 bus_space_write_1(iot, ioh, G2CNTRL, G2CNTRL_CLEAR_EISA_INT); 394 395 #ifdef AHBDEBUG 396 printf("status = 0x%x ", ahbstat); 397 #endif /* AHBDEBUG */ 398 399 /* 400 * Process the completed operation 401 */ 402 switch (ahbstat & G2INTST_INT_STAT) { 403 case AHB_ECB_OK: 404 case AHB_ECB_RECOVERED: 405 case AHB_ECB_ERR: 406 ecb = ahb_ecb_phys_kv(sc, mboxval); 407 if (!ecb) { 408 printf("%s: BAD ECB RETURNED!\n", 409 sc->sc_dev.dv_xname); 410 goto next; /* whatever it was, it'll timeout */ 411 } 412 break; 413 414 case AHB_IMMED_ERR: 415 ecb = sc->sc_immed_ecb; 416 sc->sc_immed_ecb = 0; 417 ecb->flags |= ECB_IMMED_FAIL; 418 break; 419 420 case AHB_IMMED_OK: 421 ecb = sc->sc_immed_ecb; 422 sc->sc_immed_ecb = 0; 423 break; 424 425 default: 426 printf("%s: unexpected interrupt %x\n", 427 sc->sc_dev.dv_xname, ahbstat); 428 goto next; 429 } 430 431 callout_stop(&ecb->xs->xs_callout); 432 ahb_done(sc, ecb); 433 434 next: 435 if ((bus_space_read_1(iot, ioh, G2STAT) & G2STAT_INT_PEND) == 0) 436 return 1; 437 } 438 } 439 440 integrate void 441 ahb_reset_ecb(sc, ecb) 442 struct ahb_softc *sc; 443 struct ahb_ecb *ecb; 444 { 445 446 ecb->flags = 0; 447 } 448 449 /* 450 * A ecb (and hence a mbx-out is put onto the 451 * free list. 452 */ 453 void 454 ahb_free_ecb(sc, ecb) 455 struct ahb_softc *sc; 456 struct ahb_ecb *ecb; 457 { 458 int s; 459 460 s = splbio(); 461 ahb_reset_ecb(sc, ecb); 462 TAILQ_INSERT_HEAD(&sc->sc_free_ecb, ecb, chain); 463 splx(s); 464 } 465 466 /* 467 * Create a set of ecbs and add them to the free list. 468 */ 469 integrate int 470 ahb_init_ecb(sc, ecb) 471 struct ahb_softc *sc; 472 struct ahb_ecb *ecb; 473 { 474 bus_dma_tag_t dmat = sc->sc_dmat; 475 int hashnum, error; 476 477 /* 478 * Create the DMA map for this ECB. 479 */ 480 error = bus_dmamap_create(dmat, AHB_MAXXFER, AHB_NSEG, AHB_MAXXFER, 481 0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, &ecb->dmamap_xfer); 482 if (error) { 483 printf("%s: can't create ecb dmamap_xfer\n", 484 sc->sc_dev.dv_xname); 485 return (error); 486 } 487 488 /* 489 * put in the phystokv hash table 490 * Never gets taken out. 491 */ 492 ecb->hashkey = sc->sc_dmamap_ecb->dm_segs[0].ds_addr + 493 AHB_ECB_OFF(ecb); 494 hashnum = ECB_HASH(ecb->hashkey); 495 ecb->nexthash = sc->sc_ecbhash[hashnum]; 496 sc->sc_ecbhash[hashnum] = ecb; 497 ahb_reset_ecb(sc, ecb); 498 return (0); 499 } 500 501 int 502 ahb_create_ecbs(sc, ecbstore, count) 503 struct ahb_softc *sc; 504 struct ahb_ecb *ecbstore; 505 int count; 506 { 507 struct ahb_ecb *ecb; 508 int i, error; 509 510 bzero(ecbstore, sizeof(struct ahb_ecb) * count); 511 for (i = 0; i < count; i++) { 512 ecb = &ecbstore[i]; 513 if ((error = ahb_init_ecb(sc, ecb)) != 0) { 514 printf("%s: unable to initialize ecb, error = %d\n", 515 sc->sc_dev.dv_xname, error); 516 goto out; 517 } 518 TAILQ_INSERT_TAIL(&sc->sc_free_ecb, ecb, chain); 519 } 520 out: 521 return (i); 522 } 523 524 /* 525 * Get a free ecb 526 * 527 * If there are none, see if we can allocate a new one. If so, put it in the 528 * hash table too otherwise either return an error or sleep. 529 */ 530 struct ahb_ecb * 531 ahb_get_ecb(sc) 532 struct ahb_softc *sc; 533 { 534 struct ahb_ecb *ecb; 535 int s; 536 537 s = splbio(); 538 ecb = TAILQ_FIRST(&sc->sc_free_ecb); 539 if (ecb != NULL) { 540 TAILQ_REMOVE(&sc->sc_free_ecb, ecb, chain); 541 ecb->flags |= ECB_ALLOC; 542 } 543 splx(s); 544 return (ecb); 545 } 546 547 /* 548 * given a physical address, find the ecb that it corresponds to. 549 */ 550 struct ahb_ecb * 551 ahb_ecb_phys_kv(sc, ecb_phys) 552 struct ahb_softc *sc; 553 physaddr ecb_phys; 554 { 555 int hashnum = ECB_HASH(ecb_phys); 556 struct ahb_ecb *ecb = sc->sc_ecbhash[hashnum]; 557 558 while (ecb) { 559 if (ecb->hashkey == ecb_phys) 560 break; 561 ecb = ecb->nexthash; 562 } 563 return ecb; 564 } 565 566 /* 567 * We have a ecb which has been processed by the adaptor, now we look to see 568 * how the operation went. 569 */ 570 void 571 ahb_done(sc, ecb) 572 struct ahb_softc *sc; 573 struct ahb_ecb *ecb; 574 { 575 bus_dma_tag_t dmat = sc->sc_dmat; 576 struct scsipi_sense_data *s1, *s2; 577 struct scsipi_xfer *xs = ecb->xs; 578 579 SC_DEBUG(xs->xs_periph, SCSIPI_DB2, ("ahb_done\n")); 580 581 bus_dmamap_sync(dmat, sc->sc_dmamap_ecb, 582 AHB_ECB_OFF(ecb), sizeof(struct ahb_ecb), 583 BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); 584 585 /* 586 * If we were a data transfer, unload the map that described 587 * the data buffer. 588 */ 589 if (xs->datalen) { 590 bus_dmamap_sync(dmat, ecb->dmamap_xfer, 0, 591 ecb->dmamap_xfer->dm_mapsize, 592 (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD : 593 BUS_DMASYNC_POSTWRITE); 594 bus_dmamap_unload(dmat, ecb->dmamap_xfer); 595 } 596 597 /* 598 * Otherwise, put the results of the operation 599 * into the xfer and call whoever started it 600 */ 601 if ((ecb->flags & ECB_ALLOC) == 0) { 602 printf("%s: exiting ecb not allocated!\n", sc->sc_dev.dv_xname); 603 Debugger(); 604 } 605 if (ecb->flags & ECB_IMMED) { 606 if (ecb->flags & ECB_IMMED_FAIL) 607 xs->error = XS_DRIVER_STUFFUP; 608 goto done; 609 } 610 if (xs->error == XS_NOERROR) { 611 if (ecb->ecb_status.host_stat != HS_OK) { 612 switch (ecb->ecb_status.host_stat) { 613 case HS_TIMED_OUT: /* No response */ 614 xs->error = XS_SELTIMEOUT; 615 break; 616 default: /* Other scsi protocol messes */ 617 printf("%s: host_stat %x\n", 618 sc->sc_dev.dv_xname, ecb->ecb_status.host_stat); 619 xs->error = XS_DRIVER_STUFFUP; 620 } 621 } else if (ecb->ecb_status.target_stat != SCSI_OK) { 622 switch (ecb->ecb_status.target_stat) { 623 case SCSI_CHECK: 624 s1 = &ecb->ecb_sense; 625 s2 = &xs->sense.scsi_sense; 626 *s2 = *s1; 627 xs->error = XS_SENSE; 628 break; 629 case SCSI_BUSY: 630 xs->error = XS_BUSY; 631 break; 632 default: 633 printf("%s: target_stat %x\n", 634 sc->sc_dev.dv_xname, ecb->ecb_status.target_stat); 635 xs->error = XS_DRIVER_STUFFUP; 636 } 637 } else 638 xs->resid = 0; 639 } 640 done: 641 ahb_free_ecb(sc, ecb); 642 scsipi_done(xs); 643 } 644 645 /* 646 * Start the board, ready for normal operation 647 */ 648 int 649 ahb_find(iot, ioh, sc) 650 bus_space_tag_t iot; 651 bus_space_handle_t ioh; 652 struct ahb_probe_data *sc; 653 { 654 u_char intdef; 655 int i, irq, busid; 656 int wait = 1000; /* 1 sec enough? */ 657 658 bus_space_write_1(iot, ioh, PORTADDR, PORTADDR_ENHANCED); 659 660 #define NO_NO 1 661 #ifdef NO_NO 662 /* 663 * reset board, If it doesn't respond, assume 664 * that it's not there.. good for the probe 665 */ 666 bus_space_write_1(iot, ioh, G2CNTRL, G2CNTRL_HARD_RESET); 667 delay(1000); 668 bus_space_write_1(iot, ioh, G2CNTRL, 0); 669 delay(10000); 670 while (--wait) { 671 if ((bus_space_read_1(iot, ioh, G2STAT) & G2STAT_BUSY) == 0) 672 break; 673 delay(1000); 674 } 675 if (!wait) { 676 #ifdef AHBDEBUG 677 printf("ahb_find: No answer from aha1742 board\n"); 678 #endif /* AHBDEBUG */ 679 return ENXIO; 680 } 681 i = bus_space_read_1(iot, ioh, MBOXIN0); 682 if (i) { 683 printf("self test failed, val = 0x%x\n", i); 684 return EIO; 685 } 686 687 /* Set it again, just to be sure. */ 688 bus_space_write_1(iot, ioh, PORTADDR, PORTADDR_ENHANCED); 689 #endif 690 691 while (bus_space_read_1(iot, ioh, G2STAT) & G2STAT_INT_PEND) { 692 printf("."); 693 bus_space_write_1(iot, ioh, G2CNTRL, G2CNTRL_CLEAR_EISA_INT); 694 delay(10000); 695 } 696 697 intdef = bus_space_read_1(iot, ioh, INTDEF); 698 switch (intdef & 0x07) { 699 case INT9: 700 irq = 9; 701 break; 702 case INT10: 703 irq = 10; 704 break; 705 case INT11: 706 irq = 11; 707 break; 708 case INT12: 709 irq = 12; 710 break; 711 case INT14: 712 irq = 14; 713 break; 714 case INT15: 715 irq = 15; 716 break; 717 default: 718 printf("illegal int setting %x\n", intdef); 719 return EIO; 720 } 721 722 bus_space_write_1(iot, ioh, INTDEF, (intdef | INTEN)); /* make sure we can interrupt */ 723 724 /* who are we on the scsi bus? */ 725 busid = (bus_space_read_1(iot, ioh, SCSIDEF) & HSCSIID); 726 727 /* if we want to return data, do so now */ 728 if (sc) { 729 sc->sc_irq = irq; 730 sc->sc_scsi_dev = busid; 731 } 732 733 /* 734 * Note that we are going and return (to probe) 735 */ 736 return 0; 737 } 738 739 int 740 ahb_init(sc) 741 struct ahb_softc *sc; 742 { 743 bus_dma_segment_t seg; 744 int i, error, rseg; 745 746 #define ECBSIZE (AHB_ECB_MAX * sizeof(struct ahb_ecb)) 747 748 /* 749 * Allocate the ECBs. 750 */ 751 if ((error = bus_dmamem_alloc(sc->sc_dmat, ECBSIZE, 752 PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) { 753 printf("%s: unable to allocate ecbs, error = %d\n", 754 sc->sc_dev.dv_xname, error); 755 return (error); 756 } 757 if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, 758 ECBSIZE, (caddr_t *)&sc->sc_ecbs, 759 BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { 760 printf("%s: unable to map ecbs, error = %d\n", 761 sc->sc_dev.dv_xname, error); 762 return (error); 763 } 764 765 /* 766 * Create and load the DMA map used for the ecbs. 767 */ 768 if ((error = bus_dmamap_create(sc->sc_dmat, ECBSIZE, 769 1, ECBSIZE, 0, BUS_DMA_NOWAIT, &sc->sc_dmamap_ecb)) != 0) { 770 printf("%s: unable to create ecb DMA map, error = %d\n", 771 sc->sc_dev.dv_xname, error); 772 return (error); 773 } 774 if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_ecb, 775 sc->sc_ecbs, ECBSIZE, NULL, BUS_DMA_NOWAIT)) != 0) { 776 printf("%s: unable to load ecb DMA map, error = %d\n", 777 sc->sc_dev.dv_xname, error); 778 return (error); 779 } 780 781 #undef ECBSIZE 782 783 /* 784 * Initialize the ecbs. 785 */ 786 i = ahb_create_ecbs(sc, sc->sc_ecbs, AHB_ECB_MAX); 787 if (i == 0) { 788 printf("%s: unable to create ecbs\n", 789 sc->sc_dev.dv_xname); 790 return (ENOMEM); 791 } else if (i != AHB_ECB_MAX) { 792 printf("%s: WARNING: only %d of %d ecbs created\n", 793 sc->sc_dev.dv_xname, i, AHB_ECB_MAX); 794 } 795 796 sc->sc_adapter.adapt_openings = i; 797 798 return (0); 799 } 800 801 void 802 ahbminphys(bp) 803 struct buf *bp; 804 { 805 806 if (bp->b_bcount > AHB_MAXXFER) 807 bp->b_bcount = AHB_MAXXFER; 808 minphys(bp); 809 } 810 811 /* 812 * start a scsi operation given the command and the data address. Also needs 813 * the unit, target and lu. 814 */ 815 void 816 ahb_scsipi_request(chan, req, arg) 817 struct scsipi_channel *chan; 818 scsipi_adapter_req_t req; 819 void *arg; 820 { 821 struct scsipi_xfer *xs; 822 struct scsipi_periph *periph; 823 struct ahb_softc *sc = (void *)chan->chan_adapter->adapt_dev; 824 bus_dma_tag_t dmat = sc->sc_dmat; 825 struct ahb_ecb *ecb; 826 int error, seg, flags, s; 827 828 switch (req) { 829 case ADAPTER_REQ_RUN_XFER: 830 xs = arg; 831 periph = xs->xs_periph; 832 flags = xs->xs_control; 833 834 SC_DEBUG(periph, SCSIPI_DB2, ("ahb_scsipi_request\n")); 835 836 /* Get an ECB to use. */ 837 ecb = ahb_get_ecb(sc); 838 #ifdef DIAGNOSTIC 839 /* 840 * This should never happen as we track the resources 841 * in the mid-layer. 842 */ 843 if (ecb == NULL) { 844 scsipi_printaddr(periph); 845 printf("unable to allocate ecb\n"); 846 panic("ahb_scsipi_request"); 847 } 848 #endif 849 850 ecb->xs = xs; 851 ecb->timeout = xs->timeout; 852 853 /* 854 * If it's a reset, we need to do an 'immediate' 855 * command, and store its ecb for later 856 * if there is already an immediate waiting, 857 * then WE must wait 858 */ 859 if (flags & XS_CTL_RESET) { 860 ecb->flags |= ECB_IMMED; 861 if (sc->sc_immed_ecb) { 862 ahb_free_ecb(sc, ecb); 863 xs->error = XS_BUSY; 864 scsipi_done(xs); 865 return; 866 } 867 sc->sc_immed_ecb = ecb; 868 869 s = splbio(); 870 ahb_send_immed(sc, AHB_TARG_RESET, ecb); 871 splx(s); 872 873 if ((flags & XS_CTL_POLL) == 0) 874 return; 875 876 /* 877 * If we can't use interrupts, poll on completion 878 */ 879 if (ahb_poll(sc, xs, ecb->timeout)) 880 ahb_timeout(ecb); 881 return; 882 } 883 884 /* 885 * Put all the arguments for the xfer in the ecb 886 */ 887 ecb->opcode = ECB_SCSI_OP; 888 ecb->opt1 = ECB_SES /*| ECB_DSB*/ | ECB_ARS; 889 ecb->opt2 = periph->periph_lun | ECB_NRB; 890 bcopy(xs->cmd, &ecb->scsi_cmd, 891 ecb->scsi_cmd_length = xs->cmdlen); 892 ecb->sense_ptr = sc->sc_dmamap_ecb->dm_segs[0].ds_addr + 893 AHB_ECB_OFF(ecb) + offsetof(struct ahb_ecb, ecb_sense); 894 ecb->req_sense_length = sizeof(ecb->ecb_sense); 895 ecb->status = sc->sc_dmamap_ecb->dm_segs[0].ds_addr + 896 AHB_ECB_OFF(ecb) + offsetof(struct ahb_ecb, ecb_status); 897 ecb->ecb_status.host_stat = 0x00; 898 ecb->ecb_status.target_stat = 0x00; 899 900 if (xs->datalen) { 901 /* 902 * Map the DMA transfer. 903 */ 904 #ifdef TFS 905 if (flags & XS_CTL_DATA_UIO) { 906 error = bus_dmamap_load_uio(sc->sc_dmat, 907 ecb->dmamap_xfer, (struct uio *)xs->data, 908 BUS_DMA_NOWAIT); 909 } else 910 #endif /* TFS */ 911 { 912 error = bus_dmamap_load(sc->sc_dmat, 913 ecb->dmamap_xfer, xs->data, xs->datalen, 914 NULL, BUS_DMA_NOWAIT); 915 } 916 917 switch (error) { 918 case 0: 919 break; 920 921 case ENOMEM: 922 case EAGAIN: 923 xs->error = XS_RESOURCE_SHORTAGE; 924 goto out_bad; 925 926 default: 927 xs->error = XS_DRIVER_STUFFUP; 928 printf("%s: error %d loading DMA map\n", 929 sc->sc_dev.dv_xname, error); 930 out_bad: 931 ahb_free_ecb(sc, ecb); 932 scsipi_done(xs); 933 return; 934 } 935 936 bus_dmamap_sync(dmat, ecb->dmamap_xfer, 0, 937 ecb->dmamap_xfer->dm_mapsize, 938 (flags & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD : 939 BUS_DMASYNC_PREWRITE); 940 941 /* 942 * Load the hardware scatter/gather map with the 943 * contents of the DMA map. 944 */ 945 for (seg = 0; seg < ecb->dmamap_xfer->dm_nsegs; seg++) { 946 ecb->ahb_dma[seg].seg_addr = 947 ecb->dmamap_xfer->dm_segs[seg].ds_addr; 948 ecb->ahb_dma[seg].seg_len = 949 ecb->dmamap_xfer->dm_segs[seg].ds_len; 950 } 951 952 ecb->data_addr = sc->sc_dmamap_ecb->dm_segs[0].ds_addr + 953 AHB_ECB_OFF(ecb) + 954 offsetof(struct ahb_ecb, ahb_dma); 955 ecb->data_length = ecb->dmamap_xfer->dm_nsegs * 956 sizeof(struct ahb_dma_seg); 957 ecb->opt1 |= ECB_S_G; 958 } else { /* No data xfer, use non S/G values */ 959 ecb->data_addr = (physaddr)0; 960 ecb->data_length = 0; 961 } 962 ecb->link_addr = (physaddr)0; 963 964 bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_ecb, 965 AHB_ECB_OFF(ecb), sizeof(struct ahb_ecb), 966 BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 967 968 s = splbio(); 969 ahb_send_mbox(sc, OP_START_ECB, ecb); 970 splx(s); 971 972 if ((flags & XS_CTL_POLL) == 0) 973 return; 974 975 /* 976 * If we can't use interrupts, poll on completion 977 */ 978 if (ahb_poll(sc, xs, ecb->timeout)) { 979 ahb_timeout(ecb); 980 if (ahb_poll(sc, xs, ecb->timeout)) 981 ahb_timeout(ecb); 982 } 983 return; 984 985 case ADAPTER_REQ_GROW_RESOURCES: 986 /* XXX Not supported. */ 987 return; 988 989 case ADAPTER_REQ_SET_XFER_MODE: 990 /* XXX How do we do this? */ 991 return; 992 } 993 } 994 995 /* 996 * Function to poll for command completion when in poll mode 997 */ 998 int 999 ahb_poll(sc, xs, count) 1000 struct ahb_softc *sc; 1001 struct scsipi_xfer *xs; 1002 int count; 1003 { /* in msec */ 1004 bus_space_tag_t iot = sc->sc_iot; 1005 bus_space_handle_t ioh = sc->sc_ioh; 1006 1007 while (count) { 1008 /* 1009 * If we had interrupts enabled, would we 1010 * have got an interrupt? 1011 */ 1012 if (bus_space_read_1(iot, ioh, G2STAT) & G2STAT_INT_PEND) 1013 ahbintr(sc); 1014 if (xs->xs_status & XS_STS_DONE) 1015 return 0; 1016 delay(1000); 1017 count--; 1018 } 1019 return 1; 1020 } 1021 1022 void 1023 ahb_timeout(arg) 1024 void *arg; 1025 { 1026 struct ahb_ecb *ecb = arg; 1027 struct scsipi_xfer *xs = ecb->xs; 1028 struct scsipi_periph *periph = xs->xs_periph; 1029 struct ahb_softc *sc = 1030 (void *)periph->periph_channel->chan_adapter->adapt_dev; 1031 int s; 1032 1033 scsipi_printaddr(periph); 1034 printf("timed out"); 1035 1036 s = splbio(); 1037 1038 if (ecb->flags & ECB_IMMED) { 1039 printf("\n"); 1040 ecb->flags |= ECB_IMMED_FAIL; 1041 /* XXX Must reset! */ 1042 } else 1043 1044 /* 1045 * If it has been through before, then 1046 * a previous abort has failed, don't 1047 * try abort again 1048 */ 1049 if (ecb->flags & ECB_ABORT) { 1050 /* abort timed out */ 1051 printf(" AGAIN\n"); 1052 /* XXX Must reset! */ 1053 } else { 1054 /* abort the operation that has timed out */ 1055 printf("\n"); 1056 ecb->xs->error = XS_TIMEOUT; 1057 ecb->timeout = AHB_ABORT_TIMEOUT; 1058 ecb->flags |= ECB_ABORT; 1059 ahb_send_mbox(sc, OP_ABORT_ECB, ecb); 1060 } 1061 1062 splx(s); 1063 } 1064