ahb.c revision 97208
1/* 2 * CAM SCSI device driver for the Adaptec 174X SCSI Host adapter 3 * 4 * Copyright (c) 1998 Justin T. Gibbs 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice immediately at the beginning of the file, without modification, 12 * this list of conditions, and the following disclaimer. 13 * 2. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD: head/sys/dev/ahb/ahb.c 97208 2002-05-24 05:21:36Z peter $ 29 */ 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/kernel.h> 34#include <sys/malloc.h> 35#include <sys/module.h> 36#include <sys/bus.h> 37 38#include <machine/bus_pio.h> 39#include <machine/bus.h> 40#include <machine/resource.h> 41#include <sys/rman.h> 42 43#include <cam/cam.h> 44#include <cam/cam_ccb.h> 45#include <cam/cam_sim.h> 46#include <cam/cam_xpt_sim.h> 47#include <cam/cam_debug.h> 48 49#include <cam/scsi/scsi_message.h> 50 51#include <dev/eisa/eisaconf.h> 52 53#include <dev/ahb/ahbreg.h> 54 55#define ccb_ecb_ptr spriv_ptr0 56#define ccb_ahb_ptr spriv_ptr1 57 58#define MIN(a, b) ((a) < (b) ? (a) : (b)) 59 60#define ahb_inb(ahb, port) \ 61 bus_space_read_1((ahb)->tag, (ahb)->bsh, port) 62 63#define ahb_inl(ahb, port) \ 64 bus_space_read_4((ahb)->tag, (ahb)->bsh, port) 65 66#define ahb_outb(ahb, port, value) \ 67 bus_space_write_1((ahb)->tag, (ahb)->bsh, port, value) 68 69#define ahb_outl(ahb, port, value) \ 70 bus_space_write_4((ahb)->tag, (ahb)->bsh, port, value) 71 72static const char *ahbmatch(eisa_id_t type); 73static struct ahb_softc *ahballoc(u_long unit, struct resource *res); 74static void ahbfree(struct ahb_softc *ahb); 75static int ahbreset(struct ahb_softc *ahb); 76static void ahbmapecbs(void *arg, bus_dma_segment_t *segs, 77 int nseg, int error); 78static int ahbxptattach(struct ahb_softc *ahb); 79static void ahbhandleimmed(struct ahb_softc *ahb, 80 u_int32_t mbox, u_int intstat); 81static void ahbcalcresid(struct ahb_softc *ahb, 82 struct ecb *ecb, union ccb *ccb); 83static __inline void ahbdone(struct ahb_softc *ahb, u_int32_t mbox, 84 u_int intstat); 85static void ahbintr(void *arg); 86static bus_dmamap_callback_t ahbexecuteecb; 87static void ahbaction(struct cam_sim *sim, union ccb *ccb); 88static void ahbpoll(struct cam_sim *sim); 89 90/* Our timeout handler */ 91static timeout_t ahbtimeout; 92 93static __inline struct ecb* ahbecbget(struct ahb_softc *ahb); 94static __inline void ahbecbfree(struct ahb_softc* ahb, 95 struct ecb* ecb); 96static __inline u_int32_t ahbecbvtop(struct ahb_softc *ahb, 97 struct ecb *ecb); 98static __inline struct ecb* ahbecbptov(struct ahb_softc *ahb, 99 u_int32_t ecb_addr); 100static __inline u_int32_t ahbstatuspaddr(u_int32_t ecb_paddr); 101static __inline u_int32_t ahbsensepaddr(u_int32_t ecb_paddr); 102static __inline u_int32_t ahbsgpaddr(u_int32_t ecb_paddr); 103static __inline void ahbqueuembox(struct ahb_softc *ahb, 104 u_int32_t mboxval, 105 u_int attn_code); 106 107static __inline struct ecb* 108ahbecbget(struct ahb_softc *ahb) 109{ 110 struct ecb* ecb; 111 int s; 112 113 s = splcam(); 114 if ((ecb = SLIST_FIRST(&ahb->free_ecbs)) != NULL) 115 SLIST_REMOVE_HEAD(&ahb->free_ecbs, links); 116 splx(s); 117 118 return (ecb); 119} 120 121static __inline void 122ahbecbfree(struct ahb_softc* ahb, struct ecb* ecb) 123{ 124 int s; 125 126 s = splcam(); 127 ecb->state = ECB_FREE; 128 SLIST_INSERT_HEAD(&ahb->free_ecbs, ecb, links); 129 splx(s); 130} 131 132static __inline u_int32_t 133ahbecbvtop(struct ahb_softc *ahb, struct ecb *ecb) 134{ 135 return (ahb->ecb_physbase 136 + (u_int32_t)((caddr_t)ecb - (caddr_t)ahb->ecb_array)); 137} 138 139static __inline struct ecb* 140ahbecbptov(struct ahb_softc *ahb, u_int32_t ecb_addr) 141{ 142 return (ahb->ecb_array 143 + ((struct ecb*)ecb_addr - (struct ecb*)ahb->ecb_physbase)); 144} 145 146static __inline u_int32_t 147ahbstatuspaddr(u_int32_t ecb_paddr) 148{ 149 return (ecb_paddr + offsetof(struct ecb, status)); 150} 151 152static __inline u_int32_t 153ahbsensepaddr(u_int32_t ecb_paddr) 154{ 155 return (ecb_paddr + offsetof(struct ecb, sense)); 156} 157 158static __inline u_int32_t 159ahbsgpaddr(u_int32_t ecb_paddr) 160{ 161 return (ecb_paddr + offsetof(struct ecb, sg_list)); 162} 163 164static __inline void 165ahbqueuembox(struct ahb_softc *ahb, u_int32_t mboxval, u_int attn_code) 166{ 167 u_int loopmax = 300; 168 while (--loopmax) { 169 u_int status; 170 171 status = ahb_inb(ahb, HOSTSTAT); 172 if ((status & (HOSTSTAT_MBOX_EMPTY|HOSTSTAT_BUSY)) 173 == HOSTSTAT_MBOX_EMPTY) 174 break; 175 DELAY(20); 176 } 177 if (loopmax == 0) 178 panic("ahb%ld: adapter not taking commands\n", ahb->unit); 179 180 ahb_outl(ahb, MBOXOUT0, mboxval); 181 ahb_outb(ahb, ATTN, attn_code); 182} 183 184static const char * 185ahbmatch(eisa_id_t type) 186{ 187 switch(type & 0xfffffe00) { 188 case EISA_DEVICE_ID_ADAPTEC_1740: 189 return ("Adaptec 174x SCSI host adapter"); 190 break; 191 default: 192 break; 193 } 194 return (NULL); 195} 196 197static int 198ahbprobe(device_t dev) 199{ 200 const char *desc; 201 u_int32_t iobase; 202 u_int32_t irq; 203 u_int8_t intdef; 204 int shared; 205 206 desc = ahbmatch(eisa_get_id(dev)); 207 if (!desc) 208 return (ENXIO); 209 device_set_desc(dev, desc); 210 211 iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + 212 AHB_EISA_SLOT_OFFSET; 213 214 eisa_add_iospace(dev, iobase, AHB_EISA_IOSIZE, RESVADDR_NONE); 215 216 intdef = inb(INTDEF + iobase); 217 switch (intdef & 0x7) { 218 case INT9: 219 irq = 9; 220 break; 221 case INT10: 222 irq = 10; 223 break; 224 case INT11: 225 irq = 11; 226 break; 227 case INT12: 228 irq = 12; 229 break; 230 case INT14: 231 irq = 14; 232 break; 233 case INT15: 234 irq = 15; 235 break; 236 default: 237 printf("Adaptec 174X at slot %d: illegal " 238 "irq setting %d\n", eisa_get_slot(dev), 239 (intdef & 0x7)); 240 irq = 0; 241 break; 242 } 243 if (irq == 0) 244 return ENXIO; 245 246 shared = (inb(INTDEF + iobase) & INTLEVEL) ? 247 EISA_TRIGGER_LEVEL : EISA_TRIGGER_EDGE; 248 249 eisa_add_intr(dev, irq, shared); 250 251 return 0; 252} 253 254static int 255ahbattach(device_t dev) 256{ 257 /* 258 * find unit and check we have that many defined 259 */ 260 struct ahb_softc *ahb; 261 struct ecb* next_ecb; 262 struct resource *io = 0; 263 struct resource *irq = 0; 264 int rid; 265 void *ih; 266 267 rid = 0; 268 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 269 0, ~0, 1, RF_ACTIVE); 270 if (!io) { 271 device_printf(dev, "No I/O space?!\n"); 272 return ENOMEM; 273 } 274 275 if ((ahb = ahballoc(device_get_unit(dev), io)) == NULL) { 276 goto error_exit2; 277 } 278 279 if (ahbreset(ahb) != 0) 280 goto error_exit; 281 282 rid = 0; 283 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 284 0, ~0, 1, RF_ACTIVE); 285 if (!irq) { 286 device_printf(dev, "Can't allocate interrupt\n"); 287 goto error_exit; 288 } 289 290 /* 291 * Create our DMA tags. These tags define the kinds of device 292 * accessible memory allocations and memory mappings we will 293 * need to perform during normal operation. 294 */ 295 /* DMA tag for mapping buffers into device visible space. */ 296 /* XXX Should be a child of the EISA bus dma tag */ 297 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, /*boundary*/0, 298 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 299 /*highaddr*/BUS_SPACE_MAXADDR, 300 /*filter*/NULL, /*filterarg*/NULL, 301 /*maxsize*/MAXBSIZE, /*nsegments*/AHB_NSEG, 302 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 303 /*flags*/BUS_DMA_ALLOCNOW, 304 &ahb->buffer_dmat) != 0) 305 goto error_exit; 306 307 ahb->init_level++; 308 309 /* DMA tag for our ccb structures and ha inquiry data */ 310 if (bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, /*boundary*/0, 311 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 312 /*highaddr*/BUS_SPACE_MAXADDR, 313 /*filter*/NULL, /*filterarg*/NULL, 314 (AHB_NECB * sizeof(struct ecb)) 315 + sizeof(*ahb->ha_inq_data), 316 /*nsegments*/1, 317 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 318 /*flags*/0, &ahb->ecb_dmat) != 0) 319 goto error_exit; 320 321 ahb->init_level++; 322 323 /* Allocation for our ccbs */ 324 if (bus_dmamem_alloc(ahb->ecb_dmat, (void **)&ahb->ecb_array, 325 BUS_DMA_NOWAIT, &ahb->ecb_dmamap) != 0) 326 goto error_exit; 327 328 ahb->ha_inq_data = (struct ha_inquiry_data *)&ahb->ecb_array[AHB_NECB]; 329 330 ahb->init_level++; 331 332 /* And permanently map them */ 333 bus_dmamap_load(ahb->ecb_dmat, ahb->ecb_dmamap, 334 ahb->ecb_array, AHB_NSEG * sizeof(struct ecb), 335 ahbmapecbs, ahb, /*flags*/0); 336 337 ahb->init_level++; 338 339 /* Allocate the buffer dmamaps for each of our ECBs */ 340 bzero(ahb->ecb_array, (AHB_NECB * sizeof(struct ecb)) 341 + sizeof(*ahb->ha_inq_data)); 342 next_ecb = ahb->ecb_array; 343 while (ahb->num_ecbs < AHB_NECB) { 344 u_int32_t ecb_paddr; 345 346 if (bus_dmamap_create(ahb->buffer_dmat, /*flags*/0, 347 &next_ecb->dmamap)) 348 break; 349 ecb_paddr = ahbecbvtop(ahb, next_ecb); 350 next_ecb->hecb.status_ptr = ahbstatuspaddr(ecb_paddr); 351 next_ecb->hecb.sense_ptr = ahbsensepaddr(ecb_paddr); 352 ahb->num_ecbs++; 353 ahbecbfree(ahb, next_ecb); 354 next_ecb++; 355 } 356 357 if (ahb->num_ecbs == 0) 358 goto error_exit; 359 360 ahb->init_level++; 361 362 /* 363 * Now that we know we own the resources we need, register 364 * our bus with the XPT. 365 */ 366 if (ahbxptattach(ahb)) 367 goto error_exit; 368 369 /* Enable our interrupt */ 370 bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, ahbintr, ahb, &ih); 371 return (0); 372 373error_exit: 374 /* 375 * The board's IRQ line will not be left enabled 376 * if we can't intialize correctly, so its safe 377 * to release the irq. 378 */ 379 ahbfree(ahb); 380error_exit2: 381 if (io) 382 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 383 if (irq) 384 bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 385 return (-1); 386} 387 388static struct ahb_softc * 389ahballoc(u_long unit, struct resource *res) 390{ 391 struct ahb_softc *ahb; 392 393 /* 394 * Allocate a storage area for us 395 */ 396 ahb = malloc(sizeof(struct ahb_softc), M_DEVBUF, M_NOWAIT | M_ZERO); 397 if (!ahb) { 398 printf("ahb%ld: cannot malloc!\n", unit); 399 return (NULL); 400 } 401 SLIST_INIT(&ahb->free_ecbs); 402 LIST_INIT(&ahb->pending_ccbs); 403 ahb->unit = unit; 404 ahb->tag = rman_get_bustag(res); 405 ahb->bsh = rman_get_bushandle(res); 406 ahb->disc_permitted = ~0; 407 ahb->tags_permitted = ~0; 408 409 return (ahb); 410} 411 412static void 413ahbfree(struct ahb_softc *ahb) 414{ 415 switch (ahb->init_level) { 416 default: 417 case 4: 418 bus_dmamap_unload(ahb->ecb_dmat, ahb->ecb_dmamap); 419 case 3: 420 bus_dmamem_free(ahb->ecb_dmat, ahb->ecb_array, 421 ahb->ecb_dmamap); 422 bus_dmamap_destroy(ahb->ecb_dmat, ahb->ecb_dmamap); 423 case 2: 424 bus_dma_tag_destroy(ahb->ecb_dmat); 425 case 1: 426 bus_dma_tag_destroy(ahb->buffer_dmat); 427 case 0: 428 break; 429 } 430 free(ahb, M_DEVBUF); 431} 432 433/* 434 * reset board, If it doesn't respond, return failure 435 */ 436static int 437ahbreset(struct ahb_softc *ahb) 438{ 439 int wait = 1000; /* 1 sec enough? */ 440 int test; 441 442 if ((ahb_inb(ahb, PORTADDR) & PORTADDR_ENHANCED) == 0) { 443 printf("ahb_reset: Controller not in enhanced mode\n"); 444 return (-1); 445 } 446 447 ahb_outb(ahb, CONTROL, CNTRL_HARD_RST); 448 DELAY(1000); 449 ahb_outb(ahb, CONTROL, 0); 450 while (--wait) { 451 DELAY(1000); 452 if ((ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_BUSY) == 0) 453 break; 454 } 455 456 if (wait == 0) { 457 printf("ahbreset: No answer from aha1742 board\n"); 458 return (-1); 459 } 460 if ((test = ahb_inb(ahb, MBOXIN0)) != 0) { 461 printf("ahb_reset: self test failed, val = 0x%x\n", test); 462 return (-1); 463 } 464 while (ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_INTPEND) { 465 ahb_outb(ahb, CONTROL, CNTRL_CLRINT); 466 DELAY(10000); 467 } 468 return (0); 469} 470 471static void 472ahbmapecbs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 473{ 474 struct ahb_softc* ahb; 475 476 ahb = (struct ahb_softc*)arg; 477 ahb->ecb_physbase = segs->ds_addr; 478 /* 479 * Space for adapter inquiry information is on the 480 * tail of the ecb array. 481 */ 482 ahb->ha_inq_physbase = ahbecbvtop(ahb, &ahb->ecb_array[AHB_NECB]); 483} 484 485static int 486ahbxptattach(struct ahb_softc *ahb) 487{ 488 struct cam_devq *devq; 489 struct ecb *ecb; 490 u_int i; 491 492 /* Remeber who are we on the scsi bus */ 493 ahb->scsi_id = ahb_inb(ahb, SCSIDEF) & HSCSIID; 494 495 /* Use extended translation?? */ 496 ahb->extended_trans = ahb_inb(ahb, RESV1) & EXTENDED_TRANS; 497 498 /* Fetch adapter inquiry data */ 499 ecb = ahbecbget(ahb); /* Always succeeds - no outstanding commands */ 500 ecb->hecb.opcode = ECBOP_READ_HA_INQDATA; 501 ecb->hecb.flag_word1 = FW1_SUPPRESS_URUN_ERR|FW1_ERR_STATUS_BLK_ONLY; 502 ecb->hecb.data_ptr = ahb->ha_inq_physbase; 503 ecb->hecb.data_len = sizeof(struct ha_inquiry_data); 504 ecb->hecb.sense_ptr = 0; 505 ecb->state = ECB_ACTIVE; 506 507 /* Tell the adapter about this command */ 508 ahbqueuembox(ahb, ahbecbvtop(ahb, ecb), 509 ATTN_STARTECB|ahb->scsi_id); 510 511 /* Poll for interrupt completion */ 512 for (i = 1000; ecb->state != ECB_FREE && i != 0; i--) { 513 ahbintr(ahb); 514 DELAY(1000); 515 } 516 517 ahb->num_ecbs = MIN(ahb->num_ecbs, 518 ahb->ha_inq_data->scsi_data.reserved[1]); 519 printf("ahb%ld: %.8s %s SCSI Adapter, FW Rev. %.4s, ID=%d, %d ECBs\n", 520 ahb->unit, ahb->ha_inq_data->scsi_data.product, 521 (ahb->ha_inq_data->scsi_data.flags & 0x4) ? "Differential" 522 : "Single Ended", 523 ahb->ha_inq_data->scsi_data.revision, 524 ahb->scsi_id, ahb->num_ecbs); 525 526 /* Restore sense paddr for future CCB clients */ 527 ecb->hecb.sense_ptr = ahbsensepaddr(ahbecbvtop(ahb, ecb)); 528 529 ahbecbfree(ahb, ecb); 530 531 /* 532 * Create the device queue for our SIM. 533 */ 534 devq = cam_simq_alloc(ahb->num_ecbs); 535 if (devq == NULL) 536 return (ENOMEM); 537 538 /* 539 * Construct our SIM entry 540 */ 541 ahb->sim = cam_sim_alloc(ahbaction, ahbpoll, "ahb", ahb, ahb->unit, 542 2, ahb->num_ecbs, devq); 543 if (ahb->sim == NULL) { 544 cam_simq_free(devq); 545 return (ENOMEM); 546 } 547 548 if (xpt_bus_register(ahb->sim, 0) != CAM_SUCCESS) { 549 cam_sim_free(ahb->sim, /*free_devq*/TRUE); 550 return (ENXIO); 551 } 552 553 if (xpt_create_path(&ahb->path, /*periph*/NULL, 554 cam_sim_path(ahb->sim), CAM_TARGET_WILDCARD, 555 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 556 xpt_bus_deregister(cam_sim_path(ahb->sim)); 557 cam_sim_free(ahb->sim, /*free_devq*/TRUE); 558 return (ENXIO); 559 } 560 561 /* 562 * Allow the board to generate interrupts. 563 */ 564 ahb_outb(ahb, INTDEF, ahb_inb(ahb, INTDEF) | INTEN); 565 566 return (0); 567} 568 569static void 570ahbhandleimmed(struct ahb_softc *ahb, u_int32_t mbox, u_int intstat) 571{ 572 struct ccb_hdr *ccb_h; 573 u_int target_id; 574 575 if (ahb->immed_cmd == 0) { 576 printf("ahb%ld: Immediate Command complete with no " 577 " pending command\n", ahb->unit); 578 return; 579 } 580 581 target_id = intstat & INTSTAT_TARGET_MASK; 582 583 ccb_h = LIST_FIRST(&ahb->pending_ccbs); 584 while (ccb_h != NULL) { 585 struct ecb *pending_ecb; 586 union ccb *ccb; 587 588 pending_ecb = (struct ecb *)ccb_h->ccb_ecb_ptr; 589 ccb = pending_ecb->ccb; 590 ccb_h = LIST_NEXT(ccb_h, sim_links.le); 591 if (ccb->ccb_h.target_id == target_id 592 || target_id == ahb->scsi_id) { 593 untimeout(ahbtimeout, pending_ecb, 594 ccb->ccb_h.timeout_ch); 595 LIST_REMOVE(&ccb->ccb_h, sim_links.le); 596 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) 597 bus_dmamap_unload(ahb->buffer_dmat, 598 pending_ecb->dmamap); 599 if (pending_ecb == ahb->immed_ecb) 600 ccb->ccb_h.status = 601 CAM_CMD_TIMEOUT|CAM_RELEASE_SIMQ; 602 else if (target_id == ahb->scsi_id) 603 ccb->ccb_h.status = CAM_SCSI_BUS_RESET; 604 else 605 ccb->ccb_h.status = CAM_BDR_SENT; 606 ahbecbfree(ahb, pending_ecb); 607 xpt_done(ccb); 608 } else if (ahb->immed_ecb != NULL) { 609 /* Re-instate timeout */ 610 ccb->ccb_h.timeout_ch = 611 timeout(ahbtimeout, (caddr_t)pending_ecb, 612 (ccb->ccb_h.timeout * hz) / 1000); 613 } 614 } 615 616 if (ahb->immed_ecb != NULL) { 617 ahb->immed_ecb = NULL; 618 printf("ahb%ld: No longer in timeout\n", ahb->unit); 619 } else if (target_id == ahb->scsi_id) 620 printf("ahb%ld: SCSI Bus Reset Delivered\n", ahb->unit); 621 else 622 printf("ahb%ld: Bus Device Reset Delibered to target %d\n", 623 ahb->unit, target_id); 624 625 ahb->immed_cmd = 0; 626} 627 628static void 629ahbcalcresid(struct ahb_softc *ahb, struct ecb *ecb, union ccb *ccb) 630{ 631 if (ecb->status.data_overrun != 0) { 632 /* 633 * Overrun Condition. The hardware doesn't 634 * provide a meaningful byte count in this case 635 * (the residual is always 0). Tell the XPT 636 * layer about the error. 637 */ 638 ccb->ccb_h.status = CAM_DATA_RUN_ERR; 639 } else { 640 ccb->csio.resid = ecb->status.resid_count; 641 642 if ((ecb->hecb.flag_word1 & FW1_SG_ECB) != 0) { 643 /* 644 * For S/G transfers, the adapter provides a pointer 645 * to the address in the last S/G element used and a 646 * residual for that element. So, we need to sum up 647 * the elements that follow it in order to get a real 648 * residual number. If we have an overrun, the residual 649 * reported will be 0 and we already know that all S/G 650 * segments have been exhausted, so we can skip this 651 * step. 652 */ 653 ahb_sg_t *sg; 654 int num_sg; 655 656 num_sg = ecb->hecb.data_len / sizeof(ahb_sg_t); 657 658 /* Find the S/G the adapter was working on */ 659 for (sg = ecb->sg_list; 660 num_sg != 0 && sg->addr != ecb->status.resid_addr; 661 num_sg--, sg++) 662 ; 663 664 /* Skip it */ 665 num_sg--; 666 sg++; 667 668 /* Sum the rest */ 669 for (; num_sg != 0; num_sg--, sg++) 670 ccb->csio.resid += sg->len; 671 } 672 /* Underruns are not errors */ 673 ccb->ccb_h.status = CAM_REQ_CMP; 674 } 675} 676 677static void 678ahbprocesserror(struct ahb_softc *ahb, struct ecb *ecb, union ccb *ccb) 679{ 680 struct hardware_ecb *hecb; 681 struct ecb_status *status; 682 683 hecb = &ecb->hecb; 684 status = &ecb->status; 685 switch (status->ha_status) { 686 case HS_OK: 687 ccb->csio.scsi_status = status->scsi_status; 688 if (status->scsi_status != 0) { 689 ccb->ccb_h.status = CAM_SCSI_STATUS_ERROR; 690 if (status->sense_stored) { 691 ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 692 ccb->csio.sense_resid = 693 ccb->csio.sense_len - status->sense_len; 694 bcopy(&ecb->sense, &ccb->csio.sense_data, 695 status->sense_len); 696 } 697 } 698 break; 699 case HS_TARGET_NOT_ASSIGNED: 700 ccb->ccb_h.status = CAM_PATH_INVALID; 701 break; 702 case HS_SEL_TIMEOUT: 703 ccb->ccb_h.status = CAM_SEL_TIMEOUT; 704 break; 705 case HS_DATA_RUN_ERR: 706 ahbcalcresid(ahb, ecb, ccb); 707 break; 708 case HS_UNEXPECTED_BUSFREE: 709 ccb->ccb_h.status = CAM_UNEXP_BUSFREE; 710 break; 711 case HS_INVALID_PHASE: 712 ccb->ccb_h.status = CAM_SEQUENCE_FAIL; 713 break; 714 case HS_REQUEST_SENSE_FAILED: 715 ccb->ccb_h.status = CAM_AUTOSENSE_FAIL; 716 break; 717 case HS_TAG_MSG_REJECTED: 718 { 719 struct ccb_trans_settings neg; 720 721 xpt_print_path(ccb->ccb_h.path); 722 printf("refuses tagged commands. Performing " 723 "non-tagged I/O\n"); 724 neg.flags = 0; 725 neg.valid = CCB_TRANS_TQ_VALID; 726 xpt_setup_ccb(&neg.ccb_h, ccb->ccb_h.path, /*priority*/1); 727 xpt_async(AC_TRANSFER_NEG, ccb->ccb_h.path, &neg); 728 ahb->tags_permitted &= ~(0x01 << ccb->ccb_h.target_id); 729 ccb->ccb_h.status = CAM_MSG_REJECT_REC; 730 break; 731 } 732 case HS_FIRMWARE_LOAD_REQ: 733 case HS_HARDWARE_ERR: 734 /* 735 * Tell the system that the Adapter 736 * is no longer functional. 737 */ 738 ccb->ccb_h.status = CAM_NO_HBA; 739 break; 740 case HS_CMD_ABORTED_HOST: 741 case HS_CMD_ABORTED_ADAPTER: 742 case HS_ATN_TARGET_FAILED: 743 case HS_SCSI_RESET_ADAPTER: 744 case HS_SCSI_RESET_INCOMING: 745 ccb->ccb_h.status = CAM_SCSI_BUS_RESET; 746 break; 747 case HS_INVALID_ECB_PARAM: 748 printf("ahb%ld: opcode 0x%02x, flag_word1 0x%02x, flag_word2 0x%02x\n", 749 ahb->unit, hecb->opcode, hecb->flag_word1, hecb->flag_word2); 750 ccb->ccb_h.status = CAM_SCSI_BUS_RESET; 751 break; 752 case HS_DUP_TCB_RECEIVED: 753 case HS_INVALID_OPCODE: 754 case HS_INVALID_CMD_LINK: 755 case HS_PROGRAM_CKSUM_ERROR: 756 panic("ahb%ld: Can't happen host status %x occurred", 757 ahb->unit, status->ha_status); 758 break; 759 } 760 if (ccb->ccb_h.status != CAM_REQ_CMP) { 761 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 762 ccb->ccb_h.status |= CAM_DEV_QFRZN; 763 } 764} 765 766static void 767ahbdone(struct ahb_softc *ahb, u_int32_t mbox, u_int intstat) 768{ 769 struct ecb *ecb; 770 union ccb *ccb; 771 772 ecb = ahbecbptov(ahb, mbox); 773 774 if ((ecb->state & ECB_ACTIVE) == 0) 775 panic("ecb not active"); 776 777 ccb = ecb->ccb; 778 779 if (ccb != NULL) { 780 untimeout(ahbtimeout, ecb, ccb->ccb_h.timeout_ch); 781 LIST_REMOVE(&ccb->ccb_h, sim_links.le); 782 783 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 784 bus_dmasync_op_t op; 785 786 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 787 op = BUS_DMASYNC_POSTREAD; 788 else 789 op = BUS_DMASYNC_POSTWRITE; 790 bus_dmamap_sync(ahb->buffer_dmat, ecb->dmamap, op); 791 bus_dmamap_unload(ahb->buffer_dmat, ecb->dmamap); 792 } 793 794 if ((intstat & INTSTAT_MASK) == INTSTAT_ECB_OK) { 795 ccb->ccb_h.status = CAM_REQ_CMP; 796 ccb->csio.resid = 0; 797 } else { 798 ahbprocesserror(ahb, ecb, ccb); 799 } 800 ahbecbfree(ahb, ecb); 801 xpt_done(ccb); 802 } else { 803 /* Non CCB Command */ 804 if ((intstat & INTSTAT_MASK) != INTSTAT_ECB_OK) { 805 printf("ahb%ld: Command 0%x Failed %x:%x:%x\n", 806 ahb->unit, ecb->hecb.opcode, 807 *((u_int16_t*)&ecb->status), 808 ecb->status.ha_status, ecb->status.resid_count); 809 } 810 /* Client owns this ECB and will release it. */ 811 } 812} 813 814/* 815 * Catch an interrupt from the adaptor 816 */ 817static void 818ahbintr(void *arg) 819{ 820 struct ahb_softc *ahb; 821 u_int intstat; 822 u_int32_t mbox; 823 824 ahb = (struct ahb_softc *)arg; 825 826 while (ahb_inb(ahb, HOSTSTAT) & HOSTSTAT_INTPEND) { 827 /* 828 * Fetch information about this interrupt. 829 */ 830 intstat = ahb_inb(ahb, INTSTAT); 831 mbox = ahb_inl(ahb, MBOXIN0); 832 833 /* 834 * Reset interrupt latch. 835 */ 836 ahb_outb(ahb, CONTROL, CNTRL_CLRINT); 837 838 /* 839 * Process the completed operation 840 */ 841 switch (intstat & INTSTAT_MASK) { 842 case INTSTAT_ECB_OK: 843 case INTSTAT_ECB_CMPWRETRY: 844 case INTSTAT_ECB_CMPWERR: 845 ahbdone(ahb, mbox, intstat); 846 break; 847 case INTSTAT_AEN_OCCURED: 848 if ((intstat & INTSTAT_TARGET_MASK) == ahb->scsi_id) { 849 /* Bus Reset */ 850 xpt_print_path(ahb->path); 851 switch (mbox) { 852 case HS_SCSI_RESET_ADAPTER: 853 printf("Host Adapter Initiated " 854 "Bus Reset occurred\n"); 855 break; 856 case HS_SCSI_RESET_INCOMING: 857 printf("Bus Reset Initiated " 858 "by another device occurred\n"); 859 break; 860 } 861 /* Notify the XPT */ 862 xpt_async(AC_BUS_RESET, ahb->path, NULL); 863 break; 864 } 865 printf("Unsupported initiator selection AEN occured\n"); 866 break; 867 case INTSTAT_IMMED_OK: 868 case INTSTAT_IMMED_ERR: 869 ahbhandleimmed(ahb, mbox, intstat); 870 break; 871 case INTSTAT_HW_ERR: 872 panic("Unrecoverable hardware Error Occurred\n"); 873 } 874 } 875} 876 877static void 878ahbexecuteecb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 879{ 880 struct ecb *ecb; 881 union ccb *ccb; 882 struct ahb_softc *ahb; 883 u_int32_t ecb_paddr; 884 int s; 885 886 ecb = (struct ecb *)arg; 887 ccb = ecb->ccb; 888 ahb = (struct ahb_softc *)ccb->ccb_h.ccb_ahb_ptr; 889 890 if (error != 0) { 891 if (error != EFBIG) 892 printf("ahb%ld: Unexepected error 0x%x returned from " 893 "bus_dmamap_load\n", ahb->unit, error); 894 if (ccb->ccb_h.status == CAM_REQ_INPROG) { 895 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 896 ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; 897 } 898 ahbecbfree(ahb, ecb); 899 xpt_done(ccb); 900 return; 901 } 902 903 ecb_paddr = ahbecbvtop(ahb, ecb); 904 905 if (nseg != 0) { 906 ahb_sg_t *sg; 907 bus_dma_segment_t *end_seg; 908 bus_dmasync_op_t op; 909 910 end_seg = dm_segs + nseg; 911 912 /* Copy the segments into our SG list */ 913 sg = ecb->sg_list; 914 while (dm_segs < end_seg) { 915 sg->addr = dm_segs->ds_addr; 916 sg->len = dm_segs->ds_len; 917 sg++; 918 dm_segs++; 919 } 920 921 if (nseg > 1) { 922 ecb->hecb.flag_word1 |= FW1_SG_ECB; 923 ecb->hecb.data_ptr = ahbsgpaddr(ecb_paddr); 924 ecb->hecb.data_len = sizeof(ahb_sg_t) * nseg; 925 } else { 926 ecb->hecb.data_ptr = ecb->sg_list->addr; 927 ecb->hecb.data_len = ecb->sg_list->len; 928 } 929 930 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { 931/* ecb->hecb.flag_word2 |= FW2_DATA_DIR_IN; */ 932 op = BUS_DMASYNC_PREREAD; 933 } else { 934 op = BUS_DMASYNC_PREWRITE; 935 } 936 /* ecb->hecb.flag_word2 |= FW2_CHECK_DATA_DIR; */ 937 938 bus_dmamap_sync(ahb->buffer_dmat, ecb->dmamap, op); 939 940 } else { 941 ecb->hecb.data_ptr = 0; 942 ecb->hecb.data_len = 0; 943 } 944 945 s = splcam(); 946 947 /* 948 * Last time we need to check if this CCB needs to 949 * be aborted. 950 */ 951 if (ccb->ccb_h.status != CAM_REQ_INPROG) { 952 if (nseg != 0) 953 bus_dmamap_unload(ahb->buffer_dmat, ecb->dmamap); 954 ahbecbfree(ahb, ecb); 955 xpt_done(ccb); 956 splx(s); 957 return; 958 } 959 960 ecb->state = ECB_ACTIVE; 961 ccb->ccb_h.status |= CAM_SIM_QUEUED; 962 LIST_INSERT_HEAD(&ahb->pending_ccbs, &ccb->ccb_h, sim_links.le); 963 964 /* Tell the adapter about this command */ 965 ahbqueuembox(ahb, ecb_paddr, ATTN_STARTECB|ccb->ccb_h.target_id); 966 967 ccb->ccb_h.timeout_ch = timeout(ahbtimeout, (caddr_t)ecb, 968 (ccb->ccb_h.timeout * hz) / 1000); 969 splx(s); 970} 971 972static void 973ahbaction(struct cam_sim *sim, union ccb *ccb) 974{ 975 struct ahb_softc *ahb; 976 977 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahbaction\n")); 978 979 ahb = (struct ahb_softc *)cam_sim_softc(sim); 980 981 switch (ccb->ccb_h.func_code) { 982 /* Common cases first */ 983 case XPT_SCSI_IO: /* Execute the requested I/O operation */ 984 { 985 struct ecb *ecb; 986 struct hardware_ecb *hecb; 987 988 /* 989 * get an ecb to use. 990 */ 991 if ((ecb = ahbecbget(ahb)) == NULL) { 992 /* Should never occur */ 993 panic("Failed to get an ecb"); 994 } 995 996 /* 997 * So we can find the ECB when an abort is requested 998 */ 999 ecb->ccb = ccb; 1000 ccb->ccb_h.ccb_ecb_ptr = ecb; 1001 ccb->ccb_h.ccb_ahb_ptr = ahb; 1002 1003 /* 1004 * Put all the arguments for the xfer in the ecb 1005 */ 1006 hecb = &ecb->hecb; 1007 hecb->opcode = ECBOP_INITIATOR_SCSI_CMD; 1008 hecb->flag_word1 = FW1_AUTO_REQUEST_SENSE 1009 | FW1_ERR_STATUS_BLK_ONLY; 1010 hecb->flag_word2 = ccb->ccb_h.target_lun 1011 | FW2_NO_RETRY_ON_BUSY; 1012 if ((ccb->ccb_h.flags & CAM_TAG_ACTION_VALID) != 0) { 1013 hecb->flag_word2 |= FW2_TAG_ENB 1014 | ((ccb->csio.tag_action & 0x3) 1015 << FW2_TAG_TYPE_SHIFT); 1016 } 1017 if ((ccb->ccb_h.flags & CAM_DIS_DISCONNECT) != 0) 1018 hecb->flag_word2 |= FW2_DISABLE_DISC; 1019 hecb->sense_len = ccb->csio.sense_len; 1020 hecb->cdb_len = ccb->csio.cdb_len; 1021 if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { 1022 if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) { 1023 bcopy(ccb->csio.cdb_io.cdb_ptr, 1024 hecb->cdb, hecb->cdb_len); 1025 } else { 1026 /* I guess I could map it in... */ 1027 ccb->ccb_h.status = CAM_REQ_INVALID; 1028 ahbecbfree(ahb, ecb); 1029 xpt_done(ccb); 1030 return; 1031 } 1032 } else { 1033 bcopy(ccb->csio.cdb_io.cdb_bytes, 1034 hecb->cdb, hecb->cdb_len); 1035 } 1036 1037 /* 1038 * If we have any data to send with this command, 1039 * map it into bus space. 1040 */ 1041 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1042 if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) { 1043 /* 1044 * We've been given a pointer 1045 * to a single buffer. 1046 */ 1047 if ((ccb->ccb_h.flags & CAM_DATA_PHYS)==0) { 1048 int s; 1049 int error; 1050 1051 s = splsoftvm(); 1052 error = bus_dmamap_load( 1053 ahb->buffer_dmat, 1054 ecb->dmamap, 1055 ccb->csio.data_ptr, 1056 ccb->csio.dxfer_len, 1057 ahbexecuteecb, 1058 ecb, /*flags*/0); 1059 if (error == EINPROGRESS) { 1060 /* 1061 * So as to maintain ordering, 1062 * freeze the controller queue 1063 * until our mapping is 1064 * returned. 1065 */ 1066 xpt_freeze_simq(ahb->sim, 1); 1067 ccb->ccb_h.status |= 1068 CAM_RELEASE_SIMQ; 1069 } 1070 splx(s); 1071 } else { 1072 struct bus_dma_segment seg; 1073 1074 /* Pointer to physical buffer */ 1075 seg.ds_addr = 1076 (bus_addr_t)ccb->csio.data_ptr; 1077 seg.ds_len = ccb->csio.dxfer_len; 1078 ahbexecuteecb(ecb, &seg, 1, 0); 1079 } 1080 } else { 1081 struct bus_dma_segment *segs; 1082 1083 if ((ccb->ccb_h.flags & CAM_DATA_PHYS) != 0) 1084 panic("ahbaction - Physical segment " 1085 "pointers unsupported"); 1086 1087 if ((ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) 1088 panic("btaction - Virtual segment " 1089 "addresses unsupported"); 1090 1091 /* Just use the segments provided */ 1092 segs = (struct bus_dma_segment *) 1093 ccb->csio.data_ptr; 1094 ahbexecuteecb(ecb, segs, ccb->csio.sglist_cnt, 1095 0); 1096 } 1097 } else { 1098 ahbexecuteecb(ecb, NULL, 0, 0); 1099 } 1100 break; 1101 } 1102 case XPT_EN_LUN: /* Enable LUN as a target */ 1103 case XPT_TARGET_IO: /* Execute target I/O request */ 1104 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 1105 case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 1106 case XPT_ABORT: /* Abort the specified CCB */ 1107 /* XXX Implement */ 1108 ccb->ccb_h.status = CAM_REQ_INVALID; 1109 xpt_done(ccb); 1110 break; 1111 case XPT_SET_TRAN_SETTINGS: 1112 { 1113 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1114 xpt_done(ccb); 1115 break; 1116 } 1117 case XPT_GET_TRAN_SETTINGS: 1118 /* Get default/user set transfer settings for the target */ 1119 { 1120 struct ccb_trans_settings *cts; 1121 u_int target_mask; 1122 1123 cts = &ccb->cts; 1124 target_mask = 0x01 << ccb->ccb_h.target_id; 1125 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { 1126 cts->flags = 0; 1127 if ((ahb->disc_permitted & target_mask) != 0) 1128 cts->flags |= CCB_TRANS_DISC_ENB; 1129 if ((ahb->tags_permitted & target_mask) != 0) 1130 cts->flags |= CCB_TRANS_TAG_ENB; 1131 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 1132 cts->sync_period = 25; /* 10MHz */ 1133 1134 if (cts->sync_period != 0) 1135 cts->sync_offset = 15; 1136 1137 cts->valid = CCB_TRANS_SYNC_RATE_VALID 1138 | CCB_TRANS_SYNC_OFFSET_VALID 1139 | CCB_TRANS_BUS_WIDTH_VALID 1140 | CCB_TRANS_DISC_VALID 1141 | CCB_TRANS_TQ_VALID; 1142 ccb->ccb_h.status = CAM_REQ_CMP; 1143 } else { 1144 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1145 } 1146 xpt_done(ccb); 1147 break; 1148 } 1149 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 1150 { 1151 int i; 1152 int s; 1153 1154 s = splcam(); 1155 ahb->immed_cmd = IMMED_RESET; 1156 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ccb->ccb_h.target_id); 1157 /* Poll for interrupt completion */ 1158 for (i = 1000; ahb->immed_cmd != 0 && i != 0; i--) { 1159 DELAY(1000); 1160 ahbintr(cam_sim_softc(sim)); 1161 } 1162 splx(s); 1163 break; 1164 } 1165 case XPT_CALC_GEOMETRY: 1166 { 1167 struct ccb_calc_geometry *ccg; 1168 u_int32_t size_mb; 1169 u_int32_t secs_per_cylinder; 1170 1171 ccg = &ccb->ccg; 1172 size_mb = ccg->volume_size 1173 / ((1024L * 1024L) / ccg->block_size); 1174 1175 if (size_mb > 1024 && (ahb->extended_trans != 0)) { 1176 ccg->heads = 255; 1177 ccg->secs_per_track = 63; 1178 } else { 1179 ccg->heads = 64; 1180 ccg->secs_per_track = 32; 1181 } 1182 secs_per_cylinder = ccg->heads * ccg->secs_per_track; 1183 ccg->cylinders = ccg->volume_size / secs_per_cylinder; 1184 ccb->ccb_h.status = CAM_REQ_CMP; 1185 xpt_done(ccb); 1186 break; 1187 } 1188 case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 1189 { 1190 int i; 1191 1192 ahb->immed_cmd = IMMED_RESET; 1193 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ahb->scsi_id); 1194 /* Poll for interrupt completion */ 1195 for (i = 1000; ahb->immed_cmd != 0 && i != 0; i--) 1196 DELAY(1000); 1197 ccb->ccb_h.status = CAM_REQ_CMP; 1198 xpt_done(ccb); 1199 break; 1200 } 1201 case XPT_TERM_IO: /* Terminate the I/O process */ 1202 /* XXX Implement */ 1203 ccb->ccb_h.status = CAM_REQ_INVALID; 1204 xpt_done(ccb); 1205 break; 1206 case XPT_PATH_INQ: /* Path routing inquiry */ 1207 { 1208 struct ccb_pathinq *cpi = &ccb->cpi; 1209 1210 cpi->version_num = 1; /* XXX??? */ 1211 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE; 1212 cpi->target_sprt = 0; 1213 cpi->hba_misc = 0; 1214 cpi->hba_eng_cnt = 0; 1215 cpi->max_target = 7; 1216 cpi->max_lun = 7; 1217 cpi->initiator_id = ahb->scsi_id; 1218 cpi->bus_id = cam_sim_bus(sim); 1219 cpi->base_transfer_speed = 3300; 1220 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1221 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); 1222 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 1223 cpi->unit_number = cam_sim_unit(sim); 1224 cpi->ccb_h.status = CAM_REQ_CMP; 1225 xpt_done(ccb); 1226 break; 1227 } 1228#if 0 1229 /* Need these??? */ 1230 case XPT_IMMED_NOTIFY: /* Notify Host Target driver of event */ 1231 case XPT_NOTIFY_ACK: /* Acknowledgement of event */ 1232#endif 1233 default: 1234 ccb->ccb_h.status = CAM_REQ_INVALID; 1235 xpt_done(ccb); 1236 break; 1237 } 1238} 1239 1240static void 1241ahbpoll(struct cam_sim *sim) 1242{ 1243 ahbintr(cam_sim_softc(sim)); 1244} 1245 1246static void 1247ahbtimeout(void *arg) 1248{ 1249 struct ecb *ecb; 1250 union ccb *ccb; 1251 struct ahb_softc *ahb; 1252 int s; 1253 1254 ecb = (struct ecb *)arg; 1255 ccb = ecb->ccb; 1256 ahb = (struct ahb_softc *)ccb->ccb_h.ccb_ahb_ptr; 1257 xpt_print_path(ccb->ccb_h.path); 1258 printf("ECB %p - timed out\n", (void *)ecb); 1259 1260 s = splcam(); 1261 1262 if ((ecb->state & ECB_ACTIVE) == 0) { 1263 xpt_print_path(ccb->ccb_h.path); 1264 printf("ECB %p - timed out ECB already completed\n", 1265 (void *)ecb); 1266 splx(s); 1267 return; 1268 } 1269 /* 1270 * In order to simplify the recovery process, we ask the XPT 1271 * layer to halt the queue of new transactions and we traverse 1272 * the list of pending CCBs and remove their timeouts. This 1273 * means that the driver attempts to clear only one error 1274 * condition at a time. In general, timeouts that occur 1275 * close together are related anyway, so there is no benefit 1276 * in attempting to handle errors in parrallel. Timeouts will 1277 * be reinstated when the recovery process ends. 1278 */ 1279 if ((ecb->state & ECB_DEVICE_RESET) == 0) { 1280 struct ccb_hdr *ccb_h; 1281 1282 if ((ecb->state & ECB_RELEASE_SIMQ) == 0) { 1283 xpt_freeze_simq(ahb->sim, /*count*/1); 1284 ecb->state |= ECB_RELEASE_SIMQ; 1285 } 1286 1287 ccb_h = LIST_FIRST(&ahb->pending_ccbs); 1288 while (ccb_h != NULL) { 1289 struct ecb *pending_ecb; 1290 1291 pending_ecb = (struct ecb *)ccb_h->ccb_ecb_ptr; 1292 untimeout(ahbtimeout, pending_ecb, ccb_h->timeout_ch); 1293 ccb_h = LIST_NEXT(ccb_h, sim_links.le); 1294 } 1295 1296 /* Store for our interrupt handler */ 1297 ahb->immed_ecb = ecb; 1298 1299 /* 1300 * Send a Bus Device Reset message: 1301 * The target that is holding up the bus may not 1302 * be the same as the one that triggered this timeout 1303 * (different commands have different timeout lengths), 1304 * but we have no way of determining this from our 1305 * timeout handler. Our strategy here is to queue a 1306 * BDR message to the target of the timed out command. 1307 * If this fails, we'll get another timeout 2 seconds 1308 * later which will attempt a bus reset. 1309 */ 1310 xpt_print_path(ccb->ccb_h.path); 1311 printf("Queuing BDR\n"); 1312 ecb->state |= ECB_DEVICE_RESET; 1313 ccb->ccb_h.timeout_ch = 1314 timeout(ahbtimeout, (caddr_t)ecb, 2 * hz); 1315 1316 ahb->immed_cmd = IMMED_RESET; 1317 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ccb->ccb_h.target_id); 1318 } else if ((ecb->state & ECB_SCSIBUS_RESET) != 0) { 1319 /* 1320 * Try a SCSI bus reset. We do this only if we 1321 * have already attempted to clear the condition with a BDR. 1322 */ 1323 xpt_print_path(ccb->ccb_h.path); 1324 printf("Attempting SCSI Bus reset\n"); 1325 ecb->state |= ECB_SCSIBUS_RESET; 1326 ccb->ccb_h.timeout_ch = 1327 timeout(ahbtimeout, (caddr_t)ecb, 2 * hz); 1328 ahb->immed_cmd = IMMED_RESET; 1329 ahbqueuembox(ahb, IMMED_RESET, ATTN_IMMED|ahb->scsi_id); 1330 } else { 1331 /* Bring out the hammer... */ 1332 ahbreset(ahb); 1333 1334 /* Simulate the reset complete interrupt */ 1335 ahbhandleimmed(ahb, 0, ahb->scsi_id|INTSTAT_IMMED_OK); 1336 } 1337 1338 splx(s); 1339} 1340 1341static device_method_t ahb_eisa_methods[] = { 1342 /* Device interface */ 1343 DEVMETHOD(device_probe, ahbprobe), 1344 DEVMETHOD(device_attach, ahbattach), 1345 1346 { 0, 0 } 1347}; 1348 1349static driver_t ahb_eisa_driver = { 1350 "ahb", 1351 ahb_eisa_methods, 1352 1, /* unused */ 1353}; 1354 1355static devclass_t ahb_devclass; 1356 1357DRIVER_MODULE(ahb, eisa, ahb_eisa_driver, ahb_devclass, 0, 0); 1358