89 90/* Macro to determine that a rev is potentially a new valid one 91 * so that the driver doesn't keep breaking on new revs as it 92 * did for the CF and CP. 93 */ 94#define PROBABLY_NEW_BOARD(REV) (REV > 0x43 && REV < 0x56) 95 96/* MailBox Management functions */ 97static __inline void ahanextinbox(struct aha_softc *aha); 98static __inline void ahanextoutbox(struct aha_softc *aha); 99 100static __inline void 101ahanextinbox(struct aha_softc *aha) 102{ 103 if (aha->cur_inbox == aha->last_inbox) 104 aha->cur_inbox = aha->in_boxes; 105 else 106 aha->cur_inbox++; 107} 108 109static __inline void 110ahanextoutbox(struct aha_softc *aha) 111{ 112 if (aha->cur_outbox == aha->last_outbox) 113 aha->cur_outbox = aha->out_boxes; 114 else 115 aha->cur_outbox++; 116} 117 118#define ahautoa24(u,s3) \ 119 (s3)[0] = ((u) >> 16) & 0xff; \ 120 (s3)[1] = ((u) >> 8) & 0xff; \ 121 (s3)[2] = (u) & 0xff; 122 123#define aha_a24tou(s3) \ 124 (((s3)[0] << 16) | ((s3)[1] << 8) | (s3)[2]) 125 126/* CCB Mangement functions */ 127static __inline u_int32_t ahaccbvtop(struct aha_softc *aha, 128 struct aha_ccb *bccb); 129static __inline struct aha_ccb* ahaccbptov(struct aha_softc *aha, 130 u_int32_t ccb_addr); 131 132static __inline u_int32_t 133ahaccbvtop(struct aha_softc *aha, struct aha_ccb *bccb) 134{ 135 return (aha->aha_ccb_physbase 136 + (u_int32_t)((caddr_t)bccb - (caddr_t)aha->aha_ccb_array)); 137} 138static __inline struct aha_ccb * 139ahaccbptov(struct aha_softc *aha, u_int32_t ccb_addr) 140{ 141 return (aha->aha_ccb_array + 142 + ((struct aha_ccb*)ccb_addr-(struct aha_ccb*)aha->aha_ccb_physbase)); 143} 144 145static struct aha_ccb* ahagetccb(struct aha_softc *aha); 146static __inline void ahafreeccb(struct aha_softc *aha, struct aha_ccb *bccb); 147static void ahaallocccbs(struct aha_softc *aha); 148static bus_dmamap_callback_t ahaexecuteccb; 149static void ahadone(struct aha_softc *aha, struct aha_ccb *bccb, 150 aha_mbi_comp_code_t comp_code); 151 152/* Host adapter command functions */ 153static int ahareset(struct aha_softc* aha, int hard_reset); 154 155/* Initialization functions */ 156static int ahainitmboxes(struct aha_softc *aha); 157static bus_dmamap_callback_t ahamapmboxes; 158static bus_dmamap_callback_t ahamapccbs; 159static bus_dmamap_callback_t ahamapsgs; 160 161/* Transfer Negotiation Functions */ 162static void ahafetchtransinfo(struct aha_softc *aha, 163 struct ccb_trans_settings *cts); 164 165/* CAM SIM entry points */ 166#define ccb_bccb_ptr spriv_ptr0 167#define ccb_aha_ptr spriv_ptr1 168static void ahaaction(struct cam_sim *sim, union ccb *ccb); 169static void ahapoll(struct cam_sim *sim); 170 171/* Our timeout handler */ 172timeout_t ahatimeout; 173 174u_long aha_unit = 0; 175 176/* 177 * Do our own re-probe protection until a configuration 178 * manager can do it for us. This ensures that we don't 179 * reprobe a card already found by the EISA or PCI probes. 180 */ 181struct aha_isa_port aha_isa_ports[] = 182{ 183 { 0x330, 0 }, 184 { 0x334, 0 }, 185 { 0x230, 0 }, 186 { 0x234, 0 }, 187 { 0x130, 0 }, 188 { 0x134, 0 } 189}; 190 191/* Exported functions */ 192struct aha_softc * 193aha_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh) 194{ 195 struct aha_softc *aha; 196 int i; 197 198 if (unit != AHA_TEMP_UNIT) { 199 if (unit >= NAHA) { 200 printf("aha: unit number (%d) too high\n", unit); 201 return NULL; 202 } 203 204 /* 205 * Allocate a storage area for us 206 */ 207 if (aha_softcs[unit]) { 208 printf("aha%d: memory already allocated\n", unit); 209 return NULL; 210 } 211 } 212 213 aha = malloc(sizeof(struct aha_softc), M_DEVBUF, M_NOWAIT); 214 if (!aha) { 215 printf("aha%d: cannot malloc!\n", unit); 216 return NULL; 217 } 218 bzero(aha, sizeof(struct aha_softc)); 219 SLIST_INIT(&aha->free_aha_ccbs); 220 LIST_INIT(&aha->pending_ccbs); 221 SLIST_INIT(&aha->sg_maps); 222 aha->unit = unit; 223 aha->tag = tag; 224 aha->bsh = bsh; 225 226 if (aha->unit != AHA_TEMP_UNIT) { 227 aha_softcs[unit] = aha; 228 } 229 return (aha); 230} 231 232void 233aha_free(struct aha_softc *aha) 234{ 235 switch (aha->init_level) { 236 default: 237 case 8: 238 { 239 struct sg_map_node *sg_map; 240 241 while ((sg_map = SLIST_FIRST(&aha->sg_maps))!= NULL) { 242 SLIST_REMOVE_HEAD(&aha->sg_maps, links); 243 bus_dmamap_unload(aha->sg_dmat, 244 sg_map->sg_dmamap); 245 bus_dmamem_free(aha->sg_dmat, sg_map->sg_vaddr, 246 sg_map->sg_dmamap); 247 free(sg_map, M_DEVBUF); 248 } 249 bus_dma_tag_destroy(aha->sg_dmat); 250 } 251 case 7: 252 bus_dmamap_unload(aha->ccb_dmat, aha->ccb_dmamap); 253 case 6: 254 bus_dmamap_destroy(aha->ccb_dmat, aha->ccb_dmamap); 255 bus_dmamem_free(aha->ccb_dmat, aha->aha_ccb_array, 256 aha->ccb_dmamap); 257 case 5: 258 bus_dma_tag_destroy(aha->ccb_dmat); 259 case 4: 260 bus_dmamap_unload(aha->mailbox_dmat, aha->mailbox_dmamap); 261 case 3: 262 bus_dmamem_free(aha->mailbox_dmat, aha->in_boxes, 263 aha->mailbox_dmamap); 264 bus_dmamap_destroy(aha->mailbox_dmat, aha->mailbox_dmamap); 265 case 2: 266 bus_dma_tag_destroy(aha->buffer_dmat); 267 case 1: 268 bus_dma_tag_destroy(aha->mailbox_dmat); 269 case 0: 270 } 271 if (aha->unit != AHA_TEMP_UNIT) { 272 aha_softcs[aha->unit] = NULL; 273 } 274 free(aha, M_DEVBUF); 275} 276 277/* 278 * Probe the adapter and verify that the card is an Adaptec. 279 */ 280int 281aha_probe(struct aha_softc* aha) 282{ 283 u_int status; 284 u_int intstat; 285 int error; 286 u_int8_t param; 287 board_id_data_t board_id; 288 289 /* 290 * See if the three I/O ports look reasonable. 291 * Touch the minimal number of registers in the 292 * failure case. 293 */ 294 status = aha_inb(aha, STATUS_REG); 295 if ((status == 0) 296 || (status & (DIAG_ACTIVE|CMD_REG_BUSY| 297 STATUS_REG_RSVD|CMD_INVALID)) != 0) { 298 return (ENXIO); 299 } 300 301 intstat = aha_inb(aha, INTSTAT_REG); 302 if ((intstat & INTSTAT_REG_RSVD) != 0) { 303 printf("%s: Failed Intstat Reg Test\n", aha_name(aha)); 304 return (ENXIO); 305 } 306 307 /* 308 * Get the board ID. We use this to see if we're dealing with 309 * a buslogic card or a aha card (or clone). 310 */ 311 error = aha_cmd(aha, BOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0, 312 (u_int8_t*)&board_id, sizeof(board_id), 313 DEFAULT_CMD_TIMEOUT); 314 if (error != 0) {
|
316 return (ENXIO); 317 } 318 aha->fw_major = board_id.firmware_rev_major; 319 aha->fw_minor = board_id.firmware_rev_minor; 320 aha->boardid = board_id.board_type; 321 322 /* 323 * The Buslogic cards have an id of either 0x41 or 0x42. So 324 * if those come up in the probe, we test the geometry register 325 * of the board. Adaptec boards that are this old will not have 326 * this register, and return 0xff, while buslogic cards will return 327 * something different. 328 * 329 * XXX I'm not sure how this will impact other cloned cards. 330 */ 331 if (aha->boardid <= 0x42) { 332 status = aha_inb(aha, GEOMETRY_REG); 333 if (status != 0xff) 334 return (ENXIO); 335 } 336 337 return (0); 338} 339 340/* 341 * Pull the boards setup information and record it in our softc. 342 */ 343int 344aha_fetch_adapter_info(struct aha_softc *aha) 345{ 346 setup_data_t setup_info; 347 config_data_t config_data; 348 u_int8_t length_param; 349 int error; 350 struct aha_extbios extbios; 351 352 switch (aha->boardid) { 353 case BOARD_1540_16HEAD_BIOS: 354 strcpy(aha->model, "1540 16 head BIOS"); 355 break; 356 case BOARD_1540_64HEAD_BIOS: 357 strcpy(aha->model, "1540 64 head BIOS"); 358 break; 359 case BOARD_1542: 360 strcpy(aha->model, "1540/1542 64 head BIOS"); 361 break; 362 case BOARD_1640: 363 strcpy(aha->model, "1640"); 364 break; 365 case BOARD_1740: 366 strcpy(aha->model, "1740A/1742A/1744"); 367 break; 368 case BOARD_1542C: 369 strcpy(aha->model, "1542C"); 370 break; 371 case BOARD_1542CF: 372 strcpy(aha->model, "1542CF"); 373 break; 374 case BOARD_1542CP: 375 strcpy(aha->model, "1542CP"); 376 break; 377 default: 378 strcpy(aha->model, "Unknown"); 379 break; 380 } 381 /* 382 * If we are a new type of 1542 board (anything newer than a 1542C) 383 * then disable the extended bios so that the 384 * mailbox interface is unlocked. 385 * This is also true for the 1542B Version 3.20. First Adaptec 386 * board that supports >1Gb drives. 387 * No need to check the extended bios flags as some of the 388 * extensions that cause us problems are not flagged in that byte. 389 */ 390 if (PROBABLY_NEW_BOARD(aha->boardid) || 391 (aha->boardid == 0x41 392 && aha->fw_major == 0x31 && 393 aha->fw_minor >= 0x34)) { 394 error = aha_cmd(aha, BOP_RETURN_EXT_BIOS_INFO, NULL, 395 /*paramlen*/0, (u_char *)&extbios, sizeof(extbios), 396 DEFAULT_CMD_TIMEOUT); 397 error = aha_cmd(aha, BOP_MBOX_IF_ENABLE, (u_int8_t *)&extbios, 398 /*paramlen*/2, NULL, 0, DEFAULT_CMD_TIMEOUT); 399 } 400 if (aha->boardid < 0x41) 401 printf("%s: Likely aha 1542A, which might not work properly\n", 402 aha_name(aha)); 403 404 aha->max_sg = 17; 405 aha->diff_bus = 0; 406 aha->extended_lun = 0; 407 aha->extended_trans = 0; 408 aha->max_ccbs = 17; /* Need 17 to do 64k I/O */ 409 /* Determine Sync/Wide/Disc settings */ 410 length_param = sizeof(setup_info); 411 error = aha_cmd(aha, BOP_INQUIRE_SETUP_INFO, &length_param, 412 /*paramlen*/1, (u_int8_t*)&setup_info, 413 sizeof(setup_info), DEFAULT_CMD_TIMEOUT); 414 if (error != 0) { 415 printf("%s: aha_fetch_adapter_info - Failed " 416 "Get Setup Info\n", aha_name(aha)); 417 return (error); 418 } 419 if (setup_info.initiate_sync != 0) { 420 aha->sync_permitted = ALL_TARGETS; 421 } 422 aha->disc_permitted = ALL_TARGETS; 423 424 /* We need as many mailboxes as we can have ccbs */ 425 aha->num_boxes = aha->max_ccbs; 426 427 /* Determine our SCSI ID */ 428 429 error = aha_cmd(aha, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 430 (u_int8_t*)&config_data, sizeof(config_data), 431 DEFAULT_CMD_TIMEOUT); 432 if (error != 0) { 433 printf("%s: aha_fetch_adapter_info - Failed Get Config\n", 434 aha_name(aha)); 435 return (error); 436 } 437 aha->scsi_id = config_data.scsi_id; 438 return (0); 439} 440 441/* 442 * Start the board, ready for normal operation 443 */ 444int 445aha_init(struct aha_softc* aha) 446{ 447 /* Announce the Adapter */ 448 printf("%s: AHA-%s FW Rev. %c.%c (ID=%x) ", aha_name(aha), 449 aha->model, aha->fw_major, aha->fw_minor, aha->boardid); 450 451 if (aha->diff_bus != 0) 452 printf("Diff "); 453 454 printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", aha->scsi_id, 455 aha->max_ccbs); 456 457 /* 458 * Create our DMA tags. These tags define the kinds of device 459 * accessable memory allocations and memory mappings we will 460 * need to perform during normal operation. 461 * 462 * Unless we need to further restrict the allocation, we rely 463 * on the restrictions of the parent dmat, hence the common 464 * use of MAXADDR and MAXSIZE. 465 */ 466 467 /* DMA tag for mapping buffers into device visible space. */ 468 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0, 469 /*lowaddr*/BUS_SPACE_MAXADDR, 470 /*highaddr*/BUS_SPACE_MAXADDR, 471 /*filter*/NULL, /*filterarg*/NULL, 472 /*maxsize*/MAXBSIZE, /*nsegments*/AHA_NSEG, 473 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT, 474 /*flags*/BUS_DMA_ALLOCNOW, 475 &aha->buffer_dmat) != 0) { 476 goto error_exit; 477 } 478 479 aha->init_level++; 480 /* DMA tag for our mailboxes */ 481 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0, 482 /*lowaddr*/BUS_SPACE_MAXADDR, 483 /*highaddr*/BUS_SPACE_MAXADDR, 484 /*filter*/NULL, /*filterarg*/NULL, 485 aha->num_boxes * (sizeof(aha_mbox_in_t) 486 + sizeof(aha_mbox_out_t)), 487 /*nsegments*/1, 488 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT, 489 /*flags*/0, &aha->mailbox_dmat) != 0) { 490 goto error_exit; 491 } 492 493 aha->init_level++; 494 495 /* Allocation for our mailboxes */ 496 if (bus_dmamem_alloc(aha->mailbox_dmat, (void **)&aha->out_boxes, 497 BUS_DMA_NOWAIT, &aha->mailbox_dmamap) != 0) { 498 goto error_exit; 499 } 500 501 aha->init_level++; 502 503 /* And permanently map them */ 504 bus_dmamap_load(aha->mailbox_dmat, aha->mailbox_dmamap, 505 aha->out_boxes, 506 aha->num_boxes * (sizeof(aha_mbox_in_t) 507 + sizeof(aha_mbox_out_t)), 508 ahamapmboxes, aha, /*flags*/0); 509 510 aha->init_level++; 511 512 aha->in_boxes = (aha_mbox_in_t *)&aha->out_boxes[aha->num_boxes]; 513 514 ahainitmboxes(aha); 515 516 /* DMA tag for our ccb structures */ 517 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0, 518 /*lowaddr*/BUS_SPACE_MAXADDR, 519 /*highaddr*/BUS_SPACE_MAXADDR, 520 /*filter*/NULL, /*filterarg*/NULL, 521 aha->max_ccbs * sizeof(struct aha_ccb), 522 /*nsegments*/1, 523 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT, 524 /*flags*/0, &aha->ccb_dmat) != 0) { 525 goto error_exit; 526 } 527 528 aha->init_level++; 529 530 /* Allocation for our ccbs */ 531 if (bus_dmamem_alloc(aha->ccb_dmat, (void **)&aha->aha_ccb_array, 532 BUS_DMA_NOWAIT, &aha->ccb_dmamap) != 0) { 533 goto error_exit; 534 } 535 536 aha->init_level++; 537 538 /* And permanently map them */ 539 bus_dmamap_load(aha->ccb_dmat, aha->ccb_dmamap, 540 aha->aha_ccb_array, 541 aha->max_ccbs * sizeof(struct aha_ccb), 542 ahamapccbs, aha, /*flags*/0); 543 544 aha->init_level++; 545 546 /* DMA tag for our S/G structures. We allocate in page sized chunks */ 547 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0, 548 /*lowaddr*/BUS_SPACE_MAXADDR, 549 /*highaddr*/BUS_SPACE_MAXADDR, 550 /*filter*/NULL, /*filterarg*/NULL, 551 PAGE_SIZE, /*nsegments*/1, 552 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT, 553 /*flags*/0, &aha->sg_dmat) != 0) { 554 goto error_exit; 555 } 556 557 aha->init_level++; 558 559 /* Perform initial CCB allocation */ 560 bzero(aha->aha_ccb_array, aha->max_ccbs * sizeof(struct aha_ccb)); 561 ahaallocccbs(aha); 562 563 if (aha->num_ccbs == 0) { 564 printf("%s: aha_init - Unable to allocate initial ccbs\n", 565 aha_name(aha)); 566 goto error_exit; 567 } 568 569 /* 570 * Note that we are going and return (to probe) 571 */ 572 return 0; 573 574error_exit: 575 576 return (ENXIO); 577} 578 579int 580aha_attach(struct aha_softc *aha) 581{ 582 int tagged_dev_openings; 583 struct cam_devq *devq; 584 585 /* 586 * We reserve 1 ccb for error recovery, so don't 587 * tell the XPT about it. 588 */ 589 tagged_dev_openings = 0; 590 591 /* 592 * Create the device queue for our SIM. 593 */ 594 devq = cam_simq_alloc(aha->max_ccbs - 1); 595 if (devq == NULL) 596 return (ENOMEM); 597 598 /* 599 * Construct our SIM entry 600 */ 601 aha->sim = cam_sim_alloc(ahaaction, ahapoll, "aha", aha, aha->unit, 602 2, tagged_dev_openings, devq); 603 if (aha->sim == NULL) { 604 cam_simq_free(devq); 605 return (ENOMEM); 606 } 607 608 if (xpt_bus_register(aha->sim, 0) != CAM_SUCCESS) { 609 cam_sim_free(aha->sim, /*free_devq*/TRUE); 610 return (ENXIO); 611 } 612 613 if (xpt_create_path(&aha->path, /*periph*/NULL, 614 cam_sim_path(aha->sim), CAM_TARGET_WILDCARD, 615 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 616 xpt_bus_deregister(cam_sim_path(aha->sim)); 617 cam_sim_free(aha->sim, /*free_devq*/TRUE); 618 return (ENXIO); 619 } 620 621 return (0); 622} 623 624char * 625aha_name(struct aha_softc *aha) 626{ 627 static char name[10]; 628 629 sprintf(name, "aha%d", aha->unit); 630 return (name); 631} 632 633int 634aha_check_probed_iop(u_int ioport) 635{ 636 u_int i; 637 638 for (i=0; i < AHA_NUM_ISAPORTS; i++) { 639 if (aha_isa_ports[i].addr == ioport) { 640 if (aha_isa_ports[i].probed != 0) 641 return (1); 642 else { 643 return (0); 644 } 645 } 646 } 647 return (1); 648} 649 650void 651aha_mark_probed_bio(isa_compat_io_t port) 652{ 653 if (port < BIO_DISABLED) 654 aha_isa_ports[port].probed = 1; 655} 656 657void 658aha_mark_probed_iop(u_int ioport) 659{ 660 u_int i; 661 662 for (i = 0; i < AHA_NUM_ISAPORTS; i++) { 663 if (ioport == aha_isa_ports[i].addr) { 664 aha_isa_ports[i].probed = 1; 665 break; 666 } 667 } 668} 669 670static void 671ahaallocccbs(struct aha_softc *aha) 672{ 673 struct aha_ccb *next_ccb; 674 struct sg_map_node *sg_map; 675 bus_addr_t physaddr; 676 aha_sg_t *segs; 677 int newcount; 678 int i; 679 680 next_ccb = &aha->aha_ccb_array[aha->num_ccbs]; 681 682 sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); 683 684 if (sg_map == NULL) 685 return; 686 687 /* Allocate S/G space for the next batch of CCBS */ 688 if (bus_dmamem_alloc(aha->sg_dmat, (void **)&sg_map->sg_vaddr, 689 BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { 690 free(sg_map, M_DEVBUF); 691 return; 692 } 693 694 SLIST_INSERT_HEAD(&aha->sg_maps, sg_map, links); 695 696 bus_dmamap_load(aha->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr, 697 PAGE_SIZE, ahamapsgs, aha, /*flags*/0); 698 699 segs = sg_map->sg_vaddr; 700 physaddr = sg_map->sg_physaddr; 701 702 newcount = (PAGE_SIZE / (AHA_NSEG * sizeof(aha_sg_t))); 703 for (i = 0; aha->num_ccbs < aha->max_ccbs && i < newcount; i++) { 704 int error; 705 706 next_ccb->sg_list = segs; 707 next_ccb->sg_list_phys = physaddr; 708 next_ccb->flags = BCCB_FREE; 709 error = bus_dmamap_create(aha->buffer_dmat, /*flags*/0, 710 &next_ccb->dmamap); 711 if (error != 0) 712 break; 713 SLIST_INSERT_HEAD(&aha->free_aha_ccbs, next_ccb, links); 714 segs += AHA_NSEG; 715 physaddr += (AHA_NSEG * sizeof(aha_sg_t)); 716 next_ccb++; 717 aha->num_ccbs++; 718 } 719 720 /* Reserve a CCB for error recovery */ 721 if (aha->recovery_bccb == NULL) { 722 aha->recovery_bccb = SLIST_FIRST(&aha->free_aha_ccbs); 723 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links); 724 } 725} 726 727static __inline void 728ahafreeccb(struct aha_softc *aha, struct aha_ccb *bccb) 729{ 730 int s; 731 732 s = splcam(); 733 if ((bccb->flags & BCCB_ACTIVE) != 0) 734 LIST_REMOVE(&bccb->ccb->ccb_h, sim_links.le); 735 if (aha->resource_shortage != 0 736 && (bccb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 737 bccb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 738 aha->resource_shortage = FALSE; 739 } 740 bccb->flags = BCCB_FREE; 741 SLIST_INSERT_HEAD(&aha->free_aha_ccbs, bccb, links); 742 splx(s); 743} 744 745static struct aha_ccb* 746ahagetccb(struct aha_softc *aha) 747{ 748 struct aha_ccb* bccb; 749 int s; 750 751 s = splcam(); 752 if ((bccb = SLIST_FIRST(&aha->free_aha_ccbs)) != NULL) { 753 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links); 754 } else if (aha->num_ccbs < aha->max_ccbs) { 755 ahaallocccbs(aha); 756 bccb = SLIST_FIRST(&aha->free_aha_ccbs); 757 if (bccb == NULL) 758 printf("%s: Can't malloc BCCB\n", aha_name(aha)); 759 else 760 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links); 761 } 762 splx(s); 763 764 return (bccb); 765} 766 767static void 768ahaaction(struct cam_sim *sim, union ccb *ccb) 769{ 770 struct aha_softc *aha; 771 int s; 772 773 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahaaction\n")); 774 775 aha = (struct aha_softc *)cam_sim_softc(sim); 776 777 switch (ccb->ccb_h.func_code) { 778 /* Common cases first */ 779 case XPT_SCSI_IO: /* Execute the requested I/O operation */ 780 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 781 { 782 struct aha_ccb *bccb; 783 struct aha_hccb *hccb; 784 785 /* 786 * get a bccb to use. 787 */ 788 if ((bccb = ahagetccb(aha)) == NULL) { 789 int s; 790 791 s = splcam(); 792 aha->resource_shortage = TRUE; 793 splx(s); 794 xpt_freeze_simq(aha->sim, /*count*/1); 795 ccb->ccb_h.status = CAM_REQUEUE_REQ; 796 xpt_done(ccb); 797 return; 798 } 799 800 hccb = &bccb->hccb; 801 802 /* 803 * So we can find the BCCB when an abort is requested 804 */ 805 bccb->ccb = ccb; 806 ccb->ccb_h.ccb_bccb_ptr = bccb; 807 ccb->ccb_h.ccb_aha_ptr = aha; 808 809 /* 810 * Put all the arguments for the xfer in the bccb 811 */ 812 hccb->target = ccb->ccb_h.target_id; 813 hccb->lun = ccb->ccb_h.target_lun; 814 hccb->ahastat = 0; 815 hccb->sdstat = 0; 816 817 if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 818 struct ccb_scsiio *csio; 819 struct ccb_hdr *ccbh; 820 821 csio = &ccb->csio; 822 ccbh = &csio->ccb_h; 823 hccb->opcode = INITIATOR_CCB_WRESID; 824 hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) != 0; 825 hccb->dataout = (ccb->ccb_h.flags & CAM_DIR_OUT) != 0; 826 hccb->cmd_len = csio->cdb_len; 827 if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) { 828 ccb->ccb_h.status = CAM_REQ_INVALID; 829 ahafreeccb(aha, bccb); 830 xpt_done(ccb); 831 return; 832 } 833 hccb->sense_len = csio->sense_len; 834 if ((ccbh->flags & CAM_CDB_POINTER) != 0) { 835 if ((ccbh->flags & CAM_CDB_PHYS) == 0) { 836 bcopy(csio->cdb_io.cdb_ptr, 837 hccb->scsi_cdb, hccb->cmd_len); 838 } else { 839 /* I guess I could map it in... */ 840 ccbh->status = CAM_REQ_INVALID; 841 ahafreeccb(aha, bccb); 842 xpt_done(ccb); 843 return; 844 } 845 } else { 846 bcopy(csio->cdb_io.cdb_bytes, 847 hccb->scsi_cdb, hccb->cmd_len); 848 } 849 /* 850 * If we have any data to send with this command, 851 * map it into bus space. 852 */ 853 /* Only use S/G if there is a transfer */ 854 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 855 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { 856 /* 857 * We've been given a pointer 858 * to a single buffer. 859 */ 860 if ((ccbh->flags & CAM_DATA_PHYS)==0) { 861 int s; 862 int error; 863 864 s = splsoftvm(); 865 error = bus_dmamap_load( 866 aha->buffer_dmat, 867 bccb->dmamap, 868 csio->data_ptr, 869 csio->dxfer_len, 870 ahaexecuteccb, 871 bccb, 872 /*flags*/0); 873 if (error == EINPROGRESS) { 874 /* 875 * So as to maintain 876 * ordering, freeze the 877 * controller queue 878 * until our mapping is 879 * returned. 880 */ 881 xpt_freeze_simq(aha->sim, 882 1); 883 csio->ccb_h.status |= 884 CAM_RELEASE_SIMQ; 885 } 886 splx(s); 887 } else { 888 struct bus_dma_segment seg; 889 890 /* Pointer to physical buffer */ 891 seg.ds_addr = 892 (bus_addr_t)csio->data_ptr; 893 seg.ds_len = csio->dxfer_len; 894 ahaexecuteccb(bccb, &seg, 1, 0); 895 } 896 } else { 897 struct bus_dma_segment *segs; 898 899 if ((ccbh->flags & CAM_DATA_PHYS) != 0) 900 panic("ahaaction - Physical " 901 "segment pointers " 902 "unsupported"); 903 904 if ((ccbh->flags&CAM_SG_LIST_PHYS)==0) 905 panic("ahaaction - Virtual " 906 "segment addresses " 907 "unsupported"); 908 909 /* Just use the segments provided */ 910 segs = (struct bus_dma_segment *) 911 csio->data_ptr; 912 ahaexecuteccb(bccb, segs, 913 csio->sglist_cnt, 0); 914 } 915 } else { 916 ahaexecuteccb(bccb, NULL, 0, 0); 917 } 918 } else { 919 hccb->opcode = INITIATOR_BUS_DEV_RESET; 920 /* No data transfer */ 921 hccb->datain = TRUE; 922 hccb->dataout = TRUE; 923 hccb->cmd_len = 0; 924 hccb->sense_len = 0; 925 ahaexecuteccb(bccb, NULL, 0, 0); 926 } 927 break; 928 } 929 case XPT_EN_LUN: /* Enable LUN as a target */ 930 case XPT_TARGET_IO: /* Execute target I/O request */ 931 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 932 case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 933 case XPT_ABORT: /* Abort the specified CCB */ 934 /* XXX Implement */ 935 ccb->ccb_h.status = CAM_REQ_INVALID; 936 xpt_done(ccb); 937 break; 938 case XPT_SET_TRAN_SETTINGS: 939 { 940 /* XXX Implement */ 941 ccb->ccb_h.status = CAM_REQ_CMP; 942 xpt_done(ccb); 943 break; 944 } 945 case XPT_GET_TRAN_SETTINGS: 946 /* Get default/user set transfer settings for the target */ 947 { 948 struct ccb_trans_settings *cts; 949 u_int target_mask; 950 951 cts = &ccb->cts; 952 target_mask = 0x01 << ccb->ccb_h.target_id; 953 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { 954 cts->flags = 0; 955 if ((aha->disc_permitted & target_mask) != 0) 956 cts->flags |= CCB_TRANS_DISC_ENB; 957 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 958 if ((aha->sync_permitted & target_mask) != 0) 959 cts->sync_period = 50; 960 else 961 cts->sync_period = 0; 962 963 if (cts->sync_period != 0) 964 cts->sync_offset = 15; 965 966 cts->valid = CCB_TRANS_SYNC_RATE_VALID 967 | CCB_TRANS_SYNC_OFFSET_VALID 968 | CCB_TRANS_BUS_WIDTH_VALID 969 | CCB_TRANS_DISC_VALID 970 | CCB_TRANS_TQ_VALID; 971 } else { 972 ahafetchtransinfo(aha, cts); 973 } 974 975 ccb->ccb_h.status = CAM_REQ_CMP; 976 xpt_done(ccb); 977 break; 978 } 979 case XPT_CALC_GEOMETRY: 980 { 981 struct ccb_calc_geometry *ccg; 982 u_int32_t size_mb; 983 u_int32_t secs_per_cylinder; 984 985 ccg = &ccb->ccg; 986 size_mb = ccg->volume_size 987 / ((1024L * 1024L) / ccg->block_size); 988 989 if (size_mb >= 1024 && (aha->extended_trans != 0)) { 990 if (size_mb >= 2048) { 991 ccg->heads = 255; 992 ccg->secs_per_track = 63; 993 } else { 994 ccg->heads = 128; 995 ccg->secs_per_track = 32; 996 } 997 } else { 998 ccg->heads = 64; 999 ccg->secs_per_track = 32; 1000 } 1001 secs_per_cylinder = ccg->heads * ccg->secs_per_track; 1002 ccg->cylinders = ccg->volume_size / secs_per_cylinder; 1003 ccb->ccb_h.status = CAM_REQ_CMP; 1004 xpt_done(ccb); 1005 break; 1006 } 1007 case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 1008 { 1009 ahareset(aha, /*hardreset*/TRUE); 1010 ccb->ccb_h.status = CAM_REQ_CMP; 1011 xpt_done(ccb); 1012 break; 1013 } 1014 case XPT_TERM_IO: /* Terminate the I/O process */ 1015 /* XXX Implement */ 1016 ccb->ccb_h.status = CAM_REQ_INVALID; 1017 xpt_done(ccb); 1018 break; 1019 case XPT_PATH_INQ: /* Path routing inquiry */ 1020 { 1021 struct ccb_pathinq *cpi = &ccb->cpi; 1022 1023 cpi->version_num = 1; /* XXX??? */ 1024 cpi->hba_inquiry = PI_SDTR_ABLE; 1025 cpi->target_sprt = 0; 1026 cpi->hba_misc = 0; 1027 cpi->hba_eng_cnt = 0; 1028 cpi->max_target = 7; 1029 cpi->max_lun = 7; 1030 cpi->initiator_id = aha->scsi_id; 1031 cpi->bus_id = cam_sim_bus(sim); 1032 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1033 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); 1034 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 1035 cpi->unit_number = cam_sim_unit(sim); 1036 cpi->ccb_h.status = CAM_REQ_CMP; 1037 xpt_done(ccb); 1038 break; 1039 } 1040 default: 1041 ccb->ccb_h.status = CAM_REQ_INVALID; 1042 xpt_done(ccb); 1043 break; 1044 } 1045} 1046 1047static void 1048ahaexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 1049{ 1050 struct aha_ccb *bccb; 1051 union ccb *ccb; 1052 struct aha_softc *aha; 1053 int s, i; 1054 u_int32_t paddr; 1055 1056 bccb = (struct aha_ccb *)arg; 1057 ccb = bccb->ccb; 1058 aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr; 1059 1060 if (error != 0) { 1061 if (error != EFBIG) 1062 printf("%s: Unexepected error 0x%x returned from " 1063 "bus_dmamap_load\n", aha_name(aha), error); 1064 if (ccb->ccb_h.status == CAM_REQ_INPROG) { 1065 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 1066 ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; 1067 } 1068 ahafreeccb(aha, bccb); 1069 xpt_done(ccb); 1070 return; 1071 } 1072 1073 if (nseg != 0) { 1074 aha_sg_t *sg; 1075 bus_dma_segment_t *end_seg; 1076 bus_dmasync_op_t op; 1077 1078 end_seg = dm_segs + nseg; 1079 1080 /* Copy the segments into our SG list */ 1081 sg = bccb->sg_list; 1082 while (dm_segs < end_seg) { 1083 ahautoa24(dm_segs->ds_len, sg->len); 1084 ahautoa24(dm_segs->ds_addr, sg->addr); 1085 sg++; 1086 dm_segs++; 1087 } 1088 1089 if (nseg > 1) { 1090 bccb->hccb.opcode = INITIATOR_SG_CCB_WRESID; 1091 ahautoa24((sizeof(aha_sg_t) * nseg), 1092 bccb->hccb.data_len); 1093 ahautoa24(bccb->sg_list_phys, bccb->hccb.data_addr); 1094 } else { 1095 bcopy(bccb->sg_list->len, bccb->hccb.data_len, 3); 1096 bcopy(bccb->sg_list->addr, bccb->hccb.data_addr, 3); 1097 } 1098 1099 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 1100 op = BUS_DMASYNC_PREREAD; 1101 else 1102 op = BUS_DMASYNC_PREWRITE; 1103 1104 bus_dmamap_sync(aha->buffer_dmat, bccb->dmamap, op); 1105 1106 } else { 1107 bccb->hccb.opcode = INITIATOR_CCB_WRESID; 1108 ahautoa24(0, bccb->hccb.data_len); 1109 ahautoa24(0, bccb->hccb.data_addr); 1110 } 1111 1112 s = splcam(); 1113 1114 /* 1115 * Last time we need to check if this CCB needs to 1116 * be aborted. 1117 */ 1118 if (ccb->ccb_h.status != CAM_REQ_INPROG) { 1119 if (nseg != 0) 1120 bus_dmamap_unload(aha->buffer_dmat, bccb->dmamap); 1121 ahafreeccb(aha, bccb); 1122 xpt_done(ccb); 1123 splx(s); 1124 return; 1125 } 1126 1127 bccb->flags = BCCB_ACTIVE; 1128 ccb->ccb_h.status |= CAM_SIM_QUEUED; 1129 LIST_INSERT_HEAD(&aha->pending_ccbs, &ccb->ccb_h, sim_links.le); 1130 1131 ccb->ccb_h.timeout_ch = 1132 timeout(ahatimeout, (caddr_t)bccb, 1133 (ccb->ccb_h.timeout * hz) / 1000); 1134 1135 /* Tell the adapter about this command */ 1136 paddr = ahaccbvtop(aha, bccb); 1137 ahautoa24(paddr, aha->cur_outbox->ccb_addr); 1138 if (aha->cur_outbox->action_code != BMBO_FREE) 1139 panic("%s: Too few mailboxes or to many ccbs???", aha_name(aha)); 1140 aha->cur_outbox->action_code = BMBO_START; 1141 aha_outb(aha, COMMAND_REG, BOP_START_MBOX); 1142 1143 ahanextoutbox(aha); 1144 splx(s); 1145} 1146 1147void 1148aha_intr(void *arg) 1149{ 1150 struct aha_softc *aha; 1151 u_int intstat; 1152 1153 aha = (struct aha_softc *)arg; 1154 while (((intstat = aha_inb(aha, INTSTAT_REG)) & INTR_PENDING) != 0) { 1155 if ((intstat & CMD_COMPLETE) != 0) { 1156 aha->latched_status = aha_inb(aha, STATUS_REG); 1157 aha->command_cmp = TRUE; 1158 } 1159 1160 aha_outb(aha, CONTROL_REG, RESET_INTR); 1161 1162 if ((intstat & IMB_LOADED) != 0) { 1163 while (aha->cur_inbox->comp_code != BMBI_FREE) { 1164 u_int32_t paddr; 1165 paddr = aha_a24tou(aha->cur_inbox->ccb_addr); 1166 ahadone(aha, 1167 ahaccbptov(aha, paddr), 1168 aha->cur_inbox->comp_code); 1169 aha->cur_inbox->comp_code = BMBI_FREE; 1170 ahanextinbox(aha); 1171 } 1172 } 1173 1174 if ((intstat & SCSI_BUS_RESET) != 0) { 1175 ahareset(aha, /*hardreset*/FALSE); 1176 } 1177 } 1178} 1179 1180static void 1181ahadone(struct aha_softc *aha, struct aha_ccb *bccb, aha_mbi_comp_code_t comp_code) 1182{ 1183 union ccb *ccb; 1184 struct ccb_scsiio *csio; 1185 1186 ccb = bccb->ccb; 1187 csio = &bccb->ccb->csio; 1188 1189 if ((bccb->flags & BCCB_ACTIVE) == 0) { 1190 printf("%s: ahadone - Attempt to free non-active BCCB %p\n", 1191 aha_name(aha), (void *)bccb); 1192 return; 1193 } 1194 1195 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1196 bus_dmasync_op_t op; 1197 1198 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 1199 op = BUS_DMASYNC_POSTREAD; 1200 else 1201 op = BUS_DMASYNC_POSTWRITE; 1202 bus_dmamap_sync(aha->buffer_dmat, bccb->dmamap, op); 1203 bus_dmamap_unload(aha->buffer_dmat, bccb->dmamap); 1204 } 1205 1206 if (bccb == aha->recovery_bccb) { 1207 /* 1208 * The recovery BCCB does not have a CCB associated 1209 * with it, so short circuit the normal error handling. 1210 * We now traverse our list of pending CCBs and process 1211 * any that were terminated by the recovery CCBs action. 1212 * We also reinstate timeouts for all remaining, pending, 1213 * CCBs. 1214 */ 1215 struct cam_path *path; 1216 struct ccb_hdr *ccb_h; 1217 cam_status error; 1218 1219 /* Notify all clients that a BDR occured */ 1220 error = xpt_create_path(&path, /*periph*/NULL, 1221 cam_sim_path(aha->sim), 1222 bccb->hccb.target, 1223 CAM_LUN_WILDCARD); 1224 1225 if (error == CAM_REQ_CMP) 1226 xpt_async(AC_SENT_BDR, path, NULL); 1227 1228 ccb_h = LIST_FIRST(&aha->pending_ccbs); 1229 while (ccb_h != NULL) { 1230 struct aha_ccb *pending_bccb; 1231 1232 pending_bccb = (struct aha_ccb *)ccb_h->ccb_bccb_ptr; 1233 if (pending_bccb->hccb.target == bccb->hccb.target) { 1234 pending_bccb->hccb.ahastat = AHASTAT_HA_BDR; 1235 ccb_h = LIST_NEXT(ccb_h, sim_links.le); 1236 ahadone(aha, pending_bccb, BMBI_ERROR); 1237 } else { 1238 ccb_h->timeout_ch = 1239 timeout(ahatimeout, (caddr_t)pending_bccb, 1240 (ccb_h->timeout * hz) / 1000); 1241 ccb_h = LIST_NEXT(ccb_h, sim_links.le); 1242 } 1243 } 1244 printf("%s: No longer in timeout\n", aha_name(aha)); 1245 return; 1246 } 1247 1248 untimeout(ahatimeout, bccb, ccb->ccb_h.timeout_ch); 1249 1250 switch (comp_code) { 1251 case BMBI_FREE: 1252 printf("%s: ahadone - CCB completed with free status!\n", 1253 aha_name(aha)); 1254 break; 1255 case BMBI_NOT_FOUND: 1256 printf("%s: ahadone - CCB Abort failed to find CCB\n", 1257 aha_name(aha)); 1258 break; 1259 case BMBI_ABORT: 1260 case BMBI_ERROR: 1261 /* An error occured */ 1262 switch(bccb->hccb.ahastat) { 1263 case AHASTAT_DATARUN_ERROR: 1264 if (bccb->hccb.data_len <= 0) { 1265 csio->ccb_h.status = CAM_DATA_RUN_ERR; 1266 break; 1267 } 1268 /* FALLTHROUGH */ 1269 case AHASTAT_NOERROR: 1270 csio->scsi_status = bccb->hccb.sdstat; 1271 csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 1272 switch(csio->scsi_status) { 1273 case SCSI_STATUS_CHECK_COND: 1274 case SCSI_STATUS_CMD_TERMINATED: 1275 csio->ccb_h.status |= CAM_AUTOSNS_VALID; 1276 /* 1277 * The aha writes the sense data at different 1278 * offsets based on the scsi cmd len 1279 */ 1280 bcopy((caddr_t) &bccb->hccb.scsi_cdb + 1281 bccb->hccb.cmd_len, 1282 (caddr_t) &csio->sense_data, 1283 bccb->hccb.sense_len); 1284 break; 1285 default: 1286 break; 1287 case SCSI_STATUS_OK: 1288 csio->ccb_h.status = CAM_REQ_CMP; 1289 break; 1290 } 1291 csio->resid = aha_a24tou(bccb->hccb.data_len); 1292 break; 1293 case AHASTAT_SELTIMEOUT: 1294 csio->ccb_h.status = CAM_SEL_TIMEOUT; 1295 break; 1296 case AHASTAT_UNEXPECTED_BUSFREE: 1297 csio->ccb_h.status = CAM_UNEXP_BUSFREE; 1298 break; 1299 case AHASTAT_INVALID_PHASE: 1300 csio->ccb_h.status = CAM_SEQUENCE_FAIL; 1301 break; 1302 case AHASTAT_INVALID_ACTION_CODE: 1303 panic("%s: Inavlid Action code", aha_name(aha)); 1304 break; 1305 case AHASTAT_INVALID_OPCODE: 1306 panic("%s: Inavlid CCB Opcode code %x hccb = %p", 1307 aha_name(aha), bccb->hccb.opcode, &bccb->hccb); 1308 break; 1309 case AHASTAT_LINKED_CCB_LUN_MISMATCH: 1310 /* We don't even support linked commands... */ 1311 panic("%s: Linked CCB Lun Mismatch", aha_name(aha)); 1312 break; 1313 case AHASTAT_INVALID_CCB_OR_SG_PARAM: 1314 panic("%s: Invalid CCB or SG list", aha_name(aha)); 1315 break; 1316 case AHASTAT_HA_SCSI_BUS_RESET: 1317 if ((csio->ccb_h.status & CAM_STATUS_MASK) 1318 != CAM_CMD_TIMEOUT) 1319 csio->ccb_h.status = CAM_SCSI_BUS_RESET; 1320 break; 1321 case AHASTAT_HA_BDR: 1322 if ((bccb->flags & BCCB_DEVICE_RESET) == 0) 1323 csio->ccb_h.status = CAM_BDR_SENT; 1324 else 1325 csio->ccb_h.status = CAM_CMD_TIMEOUT; 1326 break; 1327 } 1328 if (csio->ccb_h.status != CAM_REQ_CMP) { 1329 xpt_freeze_devq(csio->ccb_h.path, /*count*/1); 1330 csio->ccb_h.status |= CAM_DEV_QFRZN; 1331 } 1332 if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0) 1333 ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1334 ahafreeccb(aha, bccb); 1335 xpt_done(ccb); 1336 break; 1337 case BMBI_OK: 1338 /* All completed without incident */ 1339 /* XXX DO WE NEED TO COPY SENSE BYTES HERE???? XXX */ 1340 ccb->ccb_h.status |= CAM_REQ_CMP; 1341 if ((bccb->flags & BCCB_RELEASE_SIMQ) != 0) 1342 ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1343 ahafreeccb(aha, bccb); 1344 xpt_done(ccb); 1345 break; 1346 } 1347} 1348 1349static int 1350ahareset(struct aha_softc* aha, int hard_reset) 1351{ 1352 struct ccb_hdr *ccb_h; 1353 u_int status; 1354 u_int timeout; 1355 u_int8_t reset_type; 1356 1357 if (hard_reset != 0) 1358 reset_type = HARD_RESET; 1359 else 1360 reset_type = SOFT_RESET; 1361 aha_outb(aha, CONTROL_REG, reset_type); 1362 1363 /* Wait 5sec. for Diagnostic start */ 1364 timeout = 5 * 10000; 1365 while (--timeout) { 1366 status = aha_inb(aha, STATUS_REG); 1367 if ((status & DIAG_ACTIVE) != 0) 1368 break; 1369 DELAY(100); 1370 } 1371 if (timeout == 0) {
|