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