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