aha.c revision 42013
1/* 2 * Generic register and struct definitions for the Adaptech 154x/164x 3 * SCSI host adapters. Product specific probe and attach routines can 4 * be found in: 5 * aha 1540/1542B/1542C/1542CF/1542CP aha_isa.c 6 * 7 * Copyright (c) 1998 M. Warner Losh. 8 * All Rights Reserved. 9 * 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification, immediately at the beginning of the file. 17 * 2. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 24 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * Derived from bt.c written by: 33 * 34 * Copyright (c) 1998 Justin T. Gibbs. 35 * All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions, and the following disclaimer, 42 * without modification, immediately at the beginning of the file. 43 * 2. The name of the author may not be used to endorse or promote products 44 * derived from this software without specific prior written permission. 45 * 46 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 47 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 48 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 49 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 50 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 56 * SUCH DAMAGE. 57 * 58 * $Id: aha.c,v 1.16 1998/12/15 02:51:54 imp Exp $ 59 */ 60 61#include <sys/param.h> 62#include <sys/systm.h> 63#include <sys/malloc.h> 64#include <sys/buf.h> 65#include <sys/kernel.h> 66#include <sys/sysctl.h> 67 68#include <machine/bus_pio.h> 69#include <machine/bus.h> 70#include <machine/clock.h> 71 72#include <cam/cam.h> 73#include <cam/cam_ccb.h> 74#include <cam/cam_sim.h> 75#include <cam/cam_xpt_sim.h> 76#include <cam/cam_debug.h> 77 78#include <cam/scsi/scsi_message.h> 79 80#include <vm/vm.h> 81#include <vm/pmap.h> 82 83#include <dev/aha/ahareg.h> 84 85struct aha_softc *aha_softcs[NAHA]; 86 87#define MIN(a, b) ((a) < (b) ? (a) : (b)) 88#define PRVERB(x) if (bootverbose) printf x 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 *accb); 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 *accb) 134{ 135 return (aha->aha_ccb_physbase 136 + (u_int32_t)((caddr_t)accb - (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 *accb); 147static void ahaallocccbs(struct aha_softc *aha); 148static bus_dmamap_callback_t ahaexecuteccb; 149static void ahadone(struct aha_softc *aha, struct aha_ccb *accb, 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_accb_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 { 0x130, 0, 4 }, 184 { 0x134, 0, 5 }, 185 { 0x230, 0, 2 }, 186 { 0x234, 0, 3 }, 187 { 0x330, 0, 0 }, 188 { 0x334, 0, 1 } 189}; 190 191/* 192 * I/O ports listed in the order enumerated by the 193 * card for certain op codes. 194 */ 195u_int16_t aha_board_ports[] = 196{ 197 0x330, 198 0x334, 199 0x230, 200 0x234, 201 0x130, 202 0x134 203}; 204 205/* Exported functions */ 206struct aha_softc * 207aha_alloc(int unit, bus_space_tag_t tag, bus_space_handle_t bsh) 208{ 209 struct aha_softc *aha; 210 211 if (unit != AHA_TEMP_UNIT) { 212 if (unit >= NAHA) { 213 printf("aha: unit number (%d) too high\n", unit); 214 return NULL; 215 } 216 217 /* 218 * Allocate a storage area for us 219 */ 220 if (aha_softcs[unit]) { 221 printf("aha%d: memory already allocated\n", unit); 222 return NULL; 223 } 224 } 225 226 aha = malloc(sizeof(struct aha_softc), M_DEVBUF, M_NOWAIT); 227 if (!aha) { 228 printf("aha%d: cannot malloc!\n", unit); 229 return NULL; 230 } 231 bzero(aha, sizeof(struct aha_softc)); 232 SLIST_INIT(&aha->free_aha_ccbs); 233 LIST_INIT(&aha->pending_ccbs); 234 SLIST_INIT(&aha->sg_maps); 235 aha->unit = unit; 236 aha->tag = tag; 237 aha->bsh = bsh; 238 239 if (aha->unit != AHA_TEMP_UNIT) { 240 aha_softcs[unit] = aha; 241 } 242 return (aha); 243} 244 245void 246aha_free(struct aha_softc *aha) 247{ 248 switch (aha->init_level) { 249 default: 250 case 8: 251 { 252 struct sg_map_node *sg_map; 253 254 while ((sg_map = SLIST_FIRST(&aha->sg_maps))!= NULL) { 255 SLIST_REMOVE_HEAD(&aha->sg_maps, links); 256 bus_dmamap_unload(aha->sg_dmat, 257 sg_map->sg_dmamap); 258 bus_dmamem_free(aha->sg_dmat, sg_map->sg_vaddr, 259 sg_map->sg_dmamap); 260 free(sg_map, M_DEVBUF); 261 } 262 bus_dma_tag_destroy(aha->sg_dmat); 263 } 264 case 7: 265 bus_dmamap_unload(aha->ccb_dmat, aha->ccb_dmamap); 266 case 6: 267 bus_dmamap_destroy(aha->ccb_dmat, aha->ccb_dmamap); 268 bus_dmamem_free(aha->ccb_dmat, aha->aha_ccb_array, 269 aha->ccb_dmamap); 270 case 5: 271 bus_dma_tag_destroy(aha->ccb_dmat); 272 case 4: 273 bus_dmamap_unload(aha->mailbox_dmat, aha->mailbox_dmamap); 274 case 3: 275 bus_dmamem_free(aha->mailbox_dmat, aha->in_boxes, 276 aha->mailbox_dmamap); 277 bus_dmamap_destroy(aha->mailbox_dmat, aha->mailbox_dmamap); 278 case 2: 279 bus_dma_tag_destroy(aha->buffer_dmat); 280 case 1: 281 bus_dma_tag_destroy(aha->mailbox_dmat); 282 case 0: 283 } 284 if (aha->unit != AHA_TEMP_UNIT) { 285 aha_softcs[aha->unit] = NULL; 286 } 287 free(aha, M_DEVBUF); 288} 289 290/* 291 * Probe the adapter and verify that the card is an Adaptec. 292 */ 293int 294aha_probe(struct aha_softc* aha) 295{ 296 u_int status; 297 u_int intstat; 298 int error; 299 board_id_data_t board_id; 300 301 /* 302 * See if the three I/O ports look reasonable. 303 * Touch the minimal number of registers in the 304 * failure case. 305 */ 306 status = aha_inb(aha, STATUS_REG); 307 if ((status == 0) 308 || (status & (DIAG_ACTIVE|CMD_REG_BUSY| 309 STATUS_REG_RSVD)) != 0) { 310 PRVERB(("%s: status reg test failed %x\n", aha_name(aha), 311 status)); 312 return (ENXIO); 313 } 314 315 intstat = aha_inb(aha, INTSTAT_REG); 316 if ((intstat & INTSTAT_REG_RSVD) != 0) { 317 PRVERB(("%s: Failed Intstat Reg Test\n", aha_name(aha))); 318 return (ENXIO); 319 } 320 321 /* 322 * Looking good so far. Final test is to reset the 323 * adapter and fetch the board ID and ensure we aren't 324 * looking at a BusLogic. 325 */ 326 if ((error = ahareset(aha, /*hard_reset*/TRUE)) != 0) { 327 if (bootverbose) 328 printf("%s: Failed Reset\n", aha_name(aha)); 329 return (ENXIO); 330 } 331 332 /* 333 * Get the board ID. We use this to see if we're dealing with 334 * a buslogic card or a aha card (or clone). 335 */ 336 error = aha_cmd(aha, AOP_INQUIRE_BOARD_ID, NULL, /*parmlen*/0, 337 (u_int8_t*)&board_id, sizeof(board_id), 338 DEFAULT_CMD_TIMEOUT); 339 if (error != 0) { 340 PRVERB(("%s: INQUIRE failed %x\n", aha_name(aha), error)); 341 return (ENXIO); 342 } 343 aha->fw_major = board_id.firmware_rev_major; 344 aha->fw_minor = board_id.firmware_rev_minor; 345 aha->boardid = board_id.board_type; 346 347 /* 348 * The Buslogic cards have an id of either 0x41 or 0x42. So 349 * if those come up in the probe, we test the geometry register 350 * of the board. Adaptec boards that are this old will not have 351 * this register, and return 0xff, while buslogic cards will return 352 * something different. 353 * 354 * It appears that for reasons unknow, for the for the 355 * aha-1542B cards, we need to wait a little bit before trying 356 * to read the geometry register. I picked 10ms since we have 357 * reports that a for loop to 1000 did the trick, and this 358 * errs on the side of conservatism. Besides, no one will 359 * notice a 10mS delay here, even the 1542B card users :-) 360 * 361 * Some compatible cards return 0 here. 362 * 363 * XXX I'm not sure how this will impact other cloned cards 364 * 365 * This really should be replaced with the esetup command, since 366 * that appears to be more reliable. 367 */ 368 if (aha->boardid <= 0x42) { 369 /* Wait 10ms before reading */ 370 DELAY(10000); 371 status = aha_inb(aha, GEOMETRY_REG); 372 if (status != 0xff && status != 0x00) { 373 PRVERB(("%s: Geometry Register test failed\n", 374 aha_name(aha))); 375 return (ENXIO); 376 } 377 } 378 379 return (0); 380} 381 382/* 383 * Pull the boards setup information and record it in our softc. 384 */ 385int 386aha_fetch_adapter_info(struct aha_softc *aha) 387{ 388 setup_data_t setup_info; 389 config_data_t config_data; 390 u_int8_t length_param; 391 int error; 392 struct aha_extbios extbios; 393 394 switch (aha->boardid) { 395 case BOARD_1540_16HEAD_BIOS: 396 snprintf(aha->model, sizeof(aha->model), "1540 16 head BIOS"); 397 break; 398 case BOARD_1540_64HEAD_BIOS: 399 snprintf(aha->model, sizeof(aha->model), "1540 64 head BIOS"); 400 break; 401 case BOARD_1542: 402 snprintf(aha->model, sizeof(aha->model), "1540/1542 64 head BIOS"); 403 break; 404 case BOARD_1640: 405 snprintf(aha->model, sizeof(aha->model), "1640"); 406 break; 407 case BOARD_1740: 408 snprintf(aha->model, sizeof(aha->model), "1740A/1742A/1744"); 409 break; 410 case BOARD_1542C: 411 snprintf(aha->model, sizeof(aha->model), "1542C"); 412 break; 413 case BOARD_1542CF: 414 snprintf(aha->model, sizeof(aha->model), "1542CF"); 415 break; 416 case BOARD_1542CP: 417 snprintf(aha->model, sizeof(aha->model), "1542CP"); 418 break; 419 default: 420 snprintf(aha->model, sizeof(aha->model), "Unknown"); 421 break; 422 } 423 /* 424 * If we are a new type of 1542 board (anything newer than a 1542C) 425 * then disable the extended bios so that the 426 * mailbox interface is unlocked. 427 * This is also true for the 1542B Version 3.20. First Adaptec 428 * board that supports >1Gb drives. 429 * No need to check the extended bios flags as some of the 430 * extensions that cause us problems are not flagged in that byte. 431 */ 432 if (PROBABLY_NEW_BOARD(aha->boardid) || 433 (aha->boardid == 0x41 434 && aha->fw_major == 0x31 && 435 aha->fw_minor >= 0x34)) { 436 error = aha_cmd(aha, AOP_RETURN_EXT_BIOS_INFO, NULL, 437 /*paramlen*/0, (u_char *)&extbios, sizeof(extbios), 438 DEFAULT_CMD_TIMEOUT); 439 error = aha_cmd(aha, AOP_MBOX_IF_ENABLE, (u_int8_t *)&extbios, 440 /*paramlen*/2, NULL, 0, DEFAULT_CMD_TIMEOUT); 441 } 442 if (aha->boardid < 0x41) 443 printf("%s: Warning: aha-1542A won't likely work.\n", 444 aha_name(aha)); 445 446 aha->max_sg = 17; /* Need >= 17 to do 64k I/O */ 447 aha->diff_bus = 0; 448 aha->extended_lun = 0; 449 aha->extended_trans = 0; 450 aha->max_ccbs = 16; 451 /* Determine Sync/Wide/Disc settings */ 452 length_param = sizeof(setup_info); 453 error = aha_cmd(aha, AOP_INQUIRE_SETUP_INFO, &length_param, 454 /*paramlen*/1, (u_int8_t*)&setup_info, 455 sizeof(setup_info), DEFAULT_CMD_TIMEOUT); 456 if (error != 0) { 457 printf("%s: aha_fetch_adapter_info - Failed " 458 "Get Setup Info\n", aha_name(aha)); 459 return (error); 460 } 461 if (setup_info.initiate_sync != 0) { 462 aha->sync_permitted = ALL_TARGETS; 463 } 464 aha->disc_permitted = ALL_TARGETS; 465 466 /* We need as many mailboxes as we can have ccbs */ 467 aha->num_boxes = aha->max_ccbs; 468 469 /* Determine our SCSI ID */ 470 471 error = aha_cmd(aha, AOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 472 (u_int8_t*)&config_data, sizeof(config_data), 473 DEFAULT_CMD_TIMEOUT); 474 if (error != 0) { 475 printf("%s: aha_fetch_adapter_info - Failed Get Config\n", 476 aha_name(aha)); 477 return (error); 478 } 479 aha->scsi_id = config_data.scsi_id; 480 return (0); 481} 482 483/* 484 * Start the board, ready for normal operation 485 */ 486int 487aha_init(struct aha_softc* aha) 488{ 489 /* Announce the Adapter */ 490 printf("%s: AHA-%s FW Rev. %c.%c (ID=%x) ", aha_name(aha), 491 aha->model, aha->fw_major, aha->fw_minor, aha->boardid); 492 493 if (aha->diff_bus != 0) 494 printf("Diff "); 495 496 printf("SCSI Host Adapter, SCSI ID %d, %d CCBs\n", aha->scsi_id, 497 aha->max_ccbs); 498 499 /* 500 * Create our DMA tags. These tags define the kinds of device 501 * accessable memory allocations and memory mappings we will 502 * need to perform during normal operation. 503 * 504 * Unless we need to further restrict the allocation, we rely 505 * on the restrictions of the parent dmat, hence the common 506 * use of MAXADDR and MAXSIZE. 507 */ 508 509 /* DMA tag for mapping buffers into device visible space. */ 510 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0, 511 /*lowaddr*/BUS_SPACE_MAXADDR, 512 /*highaddr*/BUS_SPACE_MAXADDR, 513 /*filter*/NULL, /*filterarg*/NULL, 514 /*maxsize*/MAXBSIZE, /*nsegments*/AHA_NSEG, 515 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT, 516 /*flags*/BUS_DMA_ALLOCNOW, 517 &aha->buffer_dmat) != 0) { 518 goto error_exit; 519 } 520 521 aha->init_level++; 522 /* DMA tag for our mailboxes */ 523 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0, 524 /*lowaddr*/BUS_SPACE_MAXADDR, 525 /*highaddr*/BUS_SPACE_MAXADDR, 526 /*filter*/NULL, /*filterarg*/NULL, 527 aha->num_boxes * (sizeof(aha_mbox_in_t) 528 + sizeof(aha_mbox_out_t)), 529 /*nsegments*/1, 530 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT, 531 /*flags*/0, &aha->mailbox_dmat) != 0) { 532 goto error_exit; 533 } 534 535 aha->init_level++; 536 537 /* Allocation for our mailboxes */ 538 if (bus_dmamem_alloc(aha->mailbox_dmat, (void **)&aha->out_boxes, 539 BUS_DMA_NOWAIT, &aha->mailbox_dmamap) != 0) { 540 goto error_exit; 541 } 542 543 aha->init_level++; 544 545 /* And permanently map them */ 546 bus_dmamap_load(aha->mailbox_dmat, aha->mailbox_dmamap, 547 aha->out_boxes, 548 aha->num_boxes * (sizeof(aha_mbox_in_t) 549 + sizeof(aha_mbox_out_t)), 550 ahamapmboxes, aha, /*flags*/0); 551 552 aha->init_level++; 553 554 aha->in_boxes = (aha_mbox_in_t *)&aha->out_boxes[aha->num_boxes]; 555 556 ahainitmboxes(aha); 557 558 /* DMA tag for our ccb structures */ 559 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0, 560 /*lowaddr*/BUS_SPACE_MAXADDR, 561 /*highaddr*/BUS_SPACE_MAXADDR, 562 /*filter*/NULL, /*filterarg*/NULL, 563 aha->max_ccbs * sizeof(struct aha_ccb), 564 /*nsegments*/1, 565 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT, 566 /*flags*/0, &aha->ccb_dmat) != 0) { 567 goto error_exit; 568 } 569 570 aha->init_level++; 571 572 /* Allocation for our ccbs */ 573 if (bus_dmamem_alloc(aha->ccb_dmat, (void **)&aha->aha_ccb_array, 574 BUS_DMA_NOWAIT, &aha->ccb_dmamap) != 0) { 575 goto error_exit; 576 } 577 578 aha->init_level++; 579 580 /* And permanently map them */ 581 bus_dmamap_load(aha->ccb_dmat, aha->ccb_dmamap, 582 aha->aha_ccb_array, 583 aha->max_ccbs * sizeof(struct aha_ccb), 584 ahamapccbs, aha, /*flags*/0); 585 586 aha->init_level++; 587 588 /* DMA tag for our S/G structures. We allocate in page sized chunks */ 589 if (bus_dma_tag_create(aha->parent_dmat, /*alignment*/0, /*boundary*/0, 590 /*lowaddr*/BUS_SPACE_MAXADDR, 591 /*highaddr*/BUS_SPACE_MAXADDR, 592 /*filter*/NULL, /*filterarg*/NULL, 593 PAGE_SIZE, /*nsegments*/1, 594 /*maxsegsz*/BUS_SPACE_MAXSIZE_24BIT, 595 /*flags*/0, &aha->sg_dmat) != 0) { 596 goto error_exit; 597 } 598 599 aha->init_level++; 600 601 /* Perform initial CCB allocation */ 602 bzero(aha->aha_ccb_array, aha->max_ccbs * sizeof(struct aha_ccb)); 603 ahaallocccbs(aha); 604 605 if (aha->num_ccbs == 0) { 606 printf("%s: aha_init - Unable to allocate initial ccbs\n", 607 aha_name(aha)); 608 goto error_exit; 609 } 610 611 /* 612 * Note that we are going and return (to probe) 613 */ 614 return 0; 615 616error_exit: 617 618 return (ENXIO); 619} 620 621int 622aha_attach(struct aha_softc *aha) 623{ 624 int tagged_dev_openings; 625 struct cam_devq *devq; 626 627 /* 628 * We don't do tagged queueing, since the aha cards don't 629 * support it. 630 */ 631 tagged_dev_openings = 0; 632 633 /* 634 * Create the device queue for our SIM. 635 */ 636 devq = cam_simq_alloc(aha->max_ccbs - 1); 637 if (devq == NULL) 638 return (ENOMEM); 639 640 /* 641 * Construct our SIM entry 642 */ 643 aha->sim = cam_sim_alloc(ahaaction, ahapoll, "aha", aha, aha->unit, 644 2, tagged_dev_openings, devq); 645 if (aha->sim == NULL) { 646 cam_simq_free(devq); 647 return (ENOMEM); 648 } 649 650 if (xpt_bus_register(aha->sim, 0) != CAM_SUCCESS) { 651 cam_sim_free(aha->sim, /*free_devq*/TRUE); 652 return (ENXIO); 653 } 654 655 if (xpt_create_path(&aha->path, /*periph*/NULL, 656 cam_sim_path(aha->sim), CAM_TARGET_WILDCARD, 657 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 658 xpt_bus_deregister(cam_sim_path(aha->sim)); 659 cam_sim_free(aha->sim, /*free_devq*/TRUE); 660 return (ENXIO); 661 } 662 663 return (0); 664} 665 666char * 667aha_name(struct aha_softc *aha) 668{ 669 static char name[10]; 670 671 snprintf(name, sizeof(name), "aha%d", aha->unit); 672 return (name); 673} 674 675int 676aha_check_probed_iop(u_int ioport) 677{ 678 u_int i; 679 680 for (i=0; i < AHA_NUM_ISAPORTS; i++) { 681 if (aha_isa_ports[i].addr == ioport) { 682 if (aha_isa_ports[i].probed != 0) 683 return (1); 684 else { 685 return (0); 686 } 687 } 688 } 689 return (1); 690} 691 692void 693aha_mark_probed_bio(isa_compat_io_t port) 694{ 695 if (port < BIO_DISABLED) 696 aha_mark_probed_iop(aha_board_ports[port]); 697} 698 699void 700aha_mark_probed_iop(u_int ioport) 701{ 702 u_int i; 703 704 for (i = 0; i < AHA_NUM_ISAPORTS; i++) { 705 if (ioport == aha_isa_ports[i].addr) { 706 aha_isa_ports[i].probed = 1; 707 break; 708 } 709 } 710} 711 712void 713aha_find_probe_range(int ioport, int *port_index, int *max_port_index) 714{ 715 if (ioport > 0) { 716 int i; 717 718 for (i = 0;i < AHA_NUM_ISAPORTS; i++) 719 if (ioport <= aha_isa_ports[i].addr) 720 break; 721 if ((i >= AHA_NUM_ISAPORTS) 722 || (ioport != aha_isa_ports[i].addr)) { 723 printf("\n" 724"aha_isa_probe: Invalid baseport of 0x%x specified.\n" 725"aha_isa_probe: Nearest valid baseport is 0x%x.\n" 726"aha_isa_probe: Failing probe.\n", 727 ioport, 728 (i < AHA_NUM_ISAPORTS) 729 ? aha_isa_ports[i].addr 730 : aha_isa_ports[AHA_NUM_ISAPORTS - 1].addr); 731 *port_index = *max_port_index = -1; 732 return; 733 } 734 *port_index = *max_port_index = aha_isa_ports[i].bio; 735 } else { 736 *port_index = 0; 737 *max_port_index = AHA_NUM_ISAPORTS - 1; 738 } 739} 740 741int 742aha_iop_from_bio(isa_compat_io_t bio_index) 743{ 744 if (bio_index >= 0 && bio_index < AHA_NUM_ISAPORTS) 745 return (aha_board_ports[bio_index]); 746 return (-1); 747} 748 749static void 750ahaallocccbs(struct aha_softc *aha) 751{ 752 struct aha_ccb *next_ccb; 753 struct sg_map_node *sg_map; 754 bus_addr_t physaddr; 755 aha_sg_t *segs; 756 int newcount; 757 int i; 758 759 next_ccb = &aha->aha_ccb_array[aha->num_ccbs]; 760 761 sg_map = malloc(sizeof(*sg_map), M_DEVBUF, M_NOWAIT); 762 763 if (sg_map == NULL) 764 return; 765 766 /* Allocate S/G space for the next batch of CCBS */ 767 if (bus_dmamem_alloc(aha->sg_dmat, (void **)&sg_map->sg_vaddr, 768 BUS_DMA_NOWAIT, &sg_map->sg_dmamap) != 0) { 769 free(sg_map, M_DEVBUF); 770 return; 771 } 772 773 SLIST_INSERT_HEAD(&aha->sg_maps, sg_map, links); 774 775 bus_dmamap_load(aha->sg_dmat, sg_map->sg_dmamap, sg_map->sg_vaddr, 776 PAGE_SIZE, ahamapsgs, aha, /*flags*/0); 777 778 segs = sg_map->sg_vaddr; 779 physaddr = sg_map->sg_physaddr; 780 781 newcount = (PAGE_SIZE / (AHA_NSEG * sizeof(aha_sg_t))); 782 for (i = 0; aha->num_ccbs < aha->max_ccbs && i < newcount; i++) { 783 int error; 784 785 next_ccb->sg_list = segs; 786 next_ccb->sg_list_phys = physaddr; 787 next_ccb->flags = ACCB_FREE; 788 error = bus_dmamap_create(aha->buffer_dmat, /*flags*/0, 789 &next_ccb->dmamap); 790 if (error != 0) 791 break; 792 SLIST_INSERT_HEAD(&aha->free_aha_ccbs, next_ccb, links); 793 segs += AHA_NSEG; 794 physaddr += (AHA_NSEG * sizeof(aha_sg_t)); 795 next_ccb++; 796 aha->num_ccbs++; 797 } 798 799 /* Reserve a CCB for error recovery */ 800 if (aha->recovery_accb == NULL) { 801 aha->recovery_accb = SLIST_FIRST(&aha->free_aha_ccbs); 802 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links); 803 } 804} 805 806static __inline void 807ahafreeccb(struct aha_softc *aha, struct aha_ccb *accb) 808{ 809 int s; 810 811 s = splcam(); 812 if ((accb->flags & ACCB_ACTIVE) != 0) 813 LIST_REMOVE(&accb->ccb->ccb_h, sim_links.le); 814 if (aha->resource_shortage != 0 815 && (accb->ccb->ccb_h.status & CAM_RELEASE_SIMQ) == 0) { 816 accb->ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 817 aha->resource_shortage = FALSE; 818 } 819 accb->flags = ACCB_FREE; 820 SLIST_INSERT_HEAD(&aha->free_aha_ccbs, accb, links); 821 aha->active_ccbs--; 822 splx(s); 823} 824 825static struct aha_ccb* 826ahagetccb(struct aha_softc *aha) 827{ 828 struct aha_ccb* accb; 829 int s; 830 831 s = splcam(); 832 if ((accb = SLIST_FIRST(&aha->free_aha_ccbs)) != NULL) { 833 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links); 834 aha->active_ccbs++; 835 } else if (aha->num_ccbs < aha->max_ccbs) { 836 ahaallocccbs(aha); 837 accb = SLIST_FIRST(&aha->free_aha_ccbs); 838 if (accb == NULL) 839 printf("%s: Can't malloc ACCB\n", aha_name(aha)); 840 else { 841 SLIST_REMOVE_HEAD(&aha->free_aha_ccbs, links); 842 aha->active_ccbs++; 843 } 844 } 845 splx(s); 846 847 return (accb); 848} 849 850static void 851ahaaction(struct cam_sim *sim, union ccb *ccb) 852{ 853 struct aha_softc *aha; 854 855 CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahaaction\n")); 856 857 aha = (struct aha_softc *)cam_sim_softc(sim); 858 859 switch (ccb->ccb_h.func_code) { 860 /* Common cases first */ 861 case XPT_SCSI_IO: /* Execute the requested I/O operation */ 862 case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ 863 { 864 struct aha_ccb *accb; 865 struct aha_hccb *hccb; 866 867 /* 868 * get a accb to use. 869 */ 870 if ((accb = ahagetccb(aha)) == NULL) { 871 int s; 872 873 s = splcam(); 874 aha->resource_shortage = TRUE; 875 splx(s); 876 xpt_freeze_simq(aha->sim, /*count*/1); 877 ccb->ccb_h.status = CAM_REQUEUE_REQ; 878 xpt_done(ccb); 879 return; 880 } 881 882 hccb = &accb->hccb; 883 884 /* 885 * So we can find the ACCB when an abort is requested 886 */ 887 accb->ccb = ccb; 888 ccb->ccb_h.ccb_accb_ptr = accb; 889 ccb->ccb_h.ccb_aha_ptr = aha; 890 891 /* 892 * Put all the arguments for the xfer in the accb 893 */ 894 hccb->target = ccb->ccb_h.target_id; 895 hccb->lun = ccb->ccb_h.target_lun; 896 hccb->ahastat = 0; 897 hccb->sdstat = 0; 898 899 if (ccb->ccb_h.func_code == XPT_SCSI_IO) { 900 struct ccb_scsiio *csio; 901 struct ccb_hdr *ccbh; 902 903 csio = &ccb->csio; 904 ccbh = &csio->ccb_h; 905 hccb->opcode = INITIATOR_CCB_WRESID; 906 hccb->datain = (ccb->ccb_h.flags & CAM_DIR_IN) != 0; 907 hccb->dataout = (ccb->ccb_h.flags & CAM_DIR_OUT) != 0; 908 hccb->cmd_len = csio->cdb_len; 909 if (hccb->cmd_len > sizeof(hccb->scsi_cdb)) { 910 ccb->ccb_h.status = CAM_REQ_INVALID; 911 ahafreeccb(aha, accb); 912 xpt_done(ccb); 913 return; 914 } 915 hccb->sense_len = csio->sense_len; 916 if ((ccbh->flags & CAM_CDB_POINTER) != 0) { 917 if ((ccbh->flags & CAM_CDB_PHYS) == 0) { 918 bcopy(csio->cdb_io.cdb_ptr, 919 hccb->scsi_cdb, hccb->cmd_len); 920 } else { 921 /* I guess I could map it in... */ 922 ccbh->status = CAM_REQ_INVALID; 923 ahafreeccb(aha, accb); 924 xpt_done(ccb); 925 return; 926 } 927 } else { 928 bcopy(csio->cdb_io.cdb_bytes, 929 hccb->scsi_cdb, hccb->cmd_len); 930 } 931 /* 932 * If we have any data to send with this command, 933 * map it into bus space. 934 */ 935 /* Only use S/G if there is a transfer */ 936 if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 937 if ((ccbh->flags & CAM_SCATTER_VALID) == 0) { 938 /* 939 * We've been given a pointer 940 * to a single buffer. 941 */ 942 if ((ccbh->flags & CAM_DATA_PHYS)==0) { 943 int s; 944 int error; 945 946 s = splsoftvm(); 947 error = bus_dmamap_load( 948 aha->buffer_dmat, 949 accb->dmamap, 950 csio->data_ptr, 951 csio->dxfer_len, 952 ahaexecuteccb, 953 accb, 954 /*flags*/0); 955 if (error == EINPROGRESS) { 956 /* 957 * So as to maintain 958 * ordering, freeze the 959 * controller queue 960 * until our mapping is 961 * returned. 962 */ 963 xpt_freeze_simq(aha->sim, 964 1); 965 csio->ccb_h.status |= 966 CAM_RELEASE_SIMQ; 967 } 968 splx(s); 969 } else { 970 struct bus_dma_segment seg; 971 972 /* Pointer to physical buffer */ 973 seg.ds_addr = 974 (bus_addr_t)csio->data_ptr; 975 seg.ds_len = csio->dxfer_len; 976 ahaexecuteccb(accb, &seg, 1, 0); 977 } 978 } else { 979 struct bus_dma_segment *segs; 980 981 if ((ccbh->flags & CAM_DATA_PHYS) != 0) 982 panic("ahaaction - Physical " 983 "segment pointers " 984 "unsupported"); 985 986 if ((ccbh->flags&CAM_SG_LIST_PHYS)==0) 987 panic("ahaaction - Virtual " 988 "segment addresses " 989 "unsupported"); 990 991 /* Just use the segments provided */ 992 segs = (struct bus_dma_segment *) 993 csio->data_ptr; 994 ahaexecuteccb(accb, segs, 995 csio->sglist_cnt, 0); 996 } 997 } else { 998 ahaexecuteccb(accb, NULL, 0, 0); 999 } 1000 } else { 1001 hccb->opcode = INITIATOR_BUS_DEV_RESET; 1002 /* No data transfer */ 1003 hccb->datain = TRUE; 1004 hccb->dataout = TRUE; 1005 hccb->cmd_len = 0; 1006 hccb->sense_len = 0; 1007 ahaexecuteccb(accb, NULL, 0, 0); 1008 } 1009 break; 1010 } 1011 case XPT_EN_LUN: /* Enable LUN as a target */ 1012 case XPT_TARGET_IO: /* Execute target I/O request */ 1013 case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ 1014 case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ 1015 case XPT_ABORT: /* Abort the specified CCB */ 1016 /* XXX Implement */ 1017 ccb->ccb_h.status = CAM_REQ_INVALID; 1018 xpt_done(ccb); 1019 break; 1020 case XPT_SET_TRAN_SETTINGS: 1021 { 1022 /* XXX Implement */ 1023 ccb->ccb_h.status = CAM_REQ_CMP; 1024 xpt_done(ccb); 1025 break; 1026 } 1027 case XPT_GET_TRAN_SETTINGS: 1028 /* Get default/user set transfer settings for the target */ 1029 { 1030 struct ccb_trans_settings *cts; 1031 u_int target_mask; 1032 1033 cts = &ccb->cts; 1034 target_mask = 0x01 << ccb->ccb_h.target_id; 1035 if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) { 1036 cts->flags = 0; 1037 if ((aha->disc_permitted & target_mask) != 0) 1038 cts->flags |= CCB_TRANS_DISC_ENB; 1039 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 1040 if ((aha->sync_permitted & target_mask) != 0) 1041 cts->sync_period = 50; 1042 else 1043 cts->sync_period = 0; 1044 1045 if (cts->sync_period != 0) 1046 cts->sync_offset = 15; 1047 1048 cts->valid = CCB_TRANS_SYNC_RATE_VALID 1049 | CCB_TRANS_SYNC_OFFSET_VALID 1050 | CCB_TRANS_BUS_WIDTH_VALID 1051 | CCB_TRANS_DISC_VALID 1052 | CCB_TRANS_TQ_VALID; 1053 } else { 1054 ahafetchtransinfo(aha, cts); 1055 } 1056 1057 ccb->ccb_h.status = CAM_REQ_CMP; 1058 xpt_done(ccb); 1059 break; 1060 } 1061 case XPT_CALC_GEOMETRY: 1062 { 1063 struct ccb_calc_geometry *ccg; 1064 u_int32_t size_mb; 1065 u_int32_t secs_per_cylinder; 1066 1067 ccg = &ccb->ccg; 1068 size_mb = ccg->volume_size 1069 / ((1024L * 1024L) / ccg->block_size); 1070 1071 if (size_mb >= 1024 && (aha->extended_trans != 0)) { 1072 if (size_mb >= 2048) { 1073 ccg->heads = 255; 1074 ccg->secs_per_track = 63; 1075 } else { 1076 ccg->heads = 128; 1077 ccg->secs_per_track = 32; 1078 } 1079 } else { 1080 ccg->heads = 64; 1081 ccg->secs_per_track = 32; 1082 } 1083 secs_per_cylinder = ccg->heads * ccg->secs_per_track; 1084 ccg->cylinders = ccg->volume_size / secs_per_cylinder; 1085 ccb->ccb_h.status = CAM_REQ_CMP; 1086 xpt_done(ccb); 1087 break; 1088 } 1089 case XPT_RESET_BUS: /* Reset the specified SCSI bus */ 1090 { 1091 ahareset(aha, /*hardreset*/TRUE); 1092 ccb->ccb_h.status = CAM_REQ_CMP; 1093 xpt_done(ccb); 1094 break; 1095 } 1096 case XPT_TERM_IO: /* Terminate the I/O process */ 1097 /* XXX Implement */ 1098 ccb->ccb_h.status = CAM_REQ_INVALID; 1099 xpt_done(ccb); 1100 break; 1101 case XPT_PATH_INQ: /* Path routing inquiry */ 1102 { 1103 struct ccb_pathinq *cpi = &ccb->cpi; 1104 1105 cpi->version_num = 1; /* XXX??? */ 1106 cpi->hba_inquiry = PI_SDTR_ABLE; 1107 cpi->target_sprt = 0; 1108 cpi->hba_misc = 0; 1109 cpi->hba_eng_cnt = 0; 1110 cpi->max_target = 7; 1111 cpi->max_lun = 7; 1112 cpi->initiator_id = aha->scsi_id; 1113 cpi->bus_id = cam_sim_bus(sim); 1114 strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 1115 strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); 1116 strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 1117 cpi->unit_number = cam_sim_unit(sim); 1118 cpi->ccb_h.status = CAM_REQ_CMP; 1119 xpt_done(ccb); 1120 break; 1121 } 1122 default: 1123 ccb->ccb_h.status = CAM_REQ_INVALID; 1124 xpt_done(ccb); 1125 break; 1126 } 1127} 1128 1129static void 1130ahaexecuteccb(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) 1131{ 1132 struct aha_ccb *accb; 1133 union ccb *ccb; 1134 struct aha_softc *aha; 1135 int s; 1136 u_int32_t paddr; 1137 1138 accb = (struct aha_ccb *)arg; 1139 ccb = accb->ccb; 1140 aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr; 1141 1142 if (error != 0) { 1143 if (error != EFBIG) 1144 printf("%s: Unexepected error 0x%x returned from " 1145 "bus_dmamap_load\n", aha_name(aha), error); 1146 if (ccb->ccb_h.status == CAM_REQ_INPROG) { 1147 xpt_freeze_devq(ccb->ccb_h.path, /*count*/1); 1148 ccb->ccb_h.status = CAM_REQ_TOO_BIG|CAM_DEV_QFRZN; 1149 } 1150 ahafreeccb(aha, accb); 1151 xpt_done(ccb); 1152 return; 1153 } 1154 1155 if (nseg != 0) { 1156 aha_sg_t *sg; 1157 bus_dma_segment_t *end_seg; 1158 bus_dmasync_op_t op; 1159 1160 end_seg = dm_segs + nseg; 1161 1162 /* Copy the segments into our SG list */ 1163 sg = accb->sg_list; 1164 while (dm_segs < end_seg) { 1165 ahautoa24(dm_segs->ds_len, sg->len); 1166 ahautoa24(dm_segs->ds_addr, sg->addr); 1167 sg++; 1168 dm_segs++; 1169 } 1170 1171 if (nseg > 1) { 1172 accb->hccb.opcode = INITIATOR_SG_CCB_WRESID; 1173 ahautoa24((sizeof(aha_sg_t) * nseg), 1174 accb->hccb.data_len); 1175 ahautoa24(accb->sg_list_phys, accb->hccb.data_addr); 1176 } else { 1177 bcopy(accb->sg_list->len, accb->hccb.data_len, 3); 1178 bcopy(accb->sg_list->addr, accb->hccb.data_addr, 3); 1179 } 1180 1181 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 1182 op = BUS_DMASYNC_PREREAD; 1183 else 1184 op = BUS_DMASYNC_PREWRITE; 1185 1186 bus_dmamap_sync(aha->buffer_dmat, accb->dmamap, op); 1187 1188 } else { 1189 accb->hccb.opcode = INITIATOR_CCB; 1190 ahautoa24(0, accb->hccb.data_len); 1191 ahautoa24(0, accb->hccb.data_addr); 1192 } 1193 1194 s = splcam(); 1195 1196 /* 1197 * Last time we need to check if this CCB needs to 1198 * be aborted. 1199 */ 1200 if (ccb->ccb_h.status != CAM_REQ_INPROG) { 1201 if (nseg != 0) 1202 bus_dmamap_unload(aha->buffer_dmat, accb->dmamap); 1203 ahafreeccb(aha, accb); 1204 xpt_done(ccb); 1205 splx(s); 1206 return; 1207 } 1208 1209 accb->flags = ACCB_ACTIVE; 1210 ccb->ccb_h.status |= CAM_SIM_QUEUED; 1211 LIST_INSERT_HEAD(&aha->pending_ccbs, &ccb->ccb_h, sim_links.le); 1212 1213 ccb->ccb_h.timeout_ch = 1214 timeout(ahatimeout, (caddr_t)accb, 1215 (ccb->ccb_h.timeout * hz) / 1000); 1216 1217 /* Tell the adapter about this command */ 1218 if (aha->cur_outbox->action_code != AMBO_FREE) { 1219 /* 1220 * We should never encounter a busy mailbox. 1221 * If we do, warn the user, and treat it as 1222 * a resource shortage. If the controller is 1223 * hung, one of the pending transactions will 1224 * timeout causing us to start recovery operations. 1225 */ 1226 printf("%s: Encountered busy mailbox with %d out of %d " 1227 "commands active!!!", aha_name(aha), aha->active_ccbs, 1228 aha->max_ccbs); 1229 untimeout(ahatimeout, accb, ccb->ccb_h.timeout_ch); 1230 if (nseg != 0) 1231 bus_dmamap_unload(aha->buffer_dmat, accb->dmamap); 1232 ahafreeccb(aha, accb); 1233 aha->resource_shortage = TRUE; 1234 xpt_freeze_simq(aha->sim, /*count*/1); 1235 ccb->ccb_h.status = CAM_REQUEUE_REQ; 1236 xpt_done(ccb); 1237 return; 1238 } 1239 paddr = ahaccbvtop(aha, accb); 1240 ahautoa24(paddr, aha->cur_outbox->ccb_addr); 1241 aha->cur_outbox->action_code = AMBO_START; 1242 aha_outb(aha, COMMAND_REG, AOP_START_MBOX); 1243 1244 ahanextoutbox(aha); 1245 splx(s); 1246} 1247 1248void 1249aha_intr(void *arg) 1250{ 1251 struct aha_softc *aha; 1252 u_int intstat; 1253 1254 aha = (struct aha_softc *)arg; 1255 while (((intstat = aha_inb(aha, INTSTAT_REG)) & INTR_PENDING) != 0) { 1256 if ((intstat & CMD_COMPLETE) != 0) { 1257 aha->latched_status = aha_inb(aha, STATUS_REG); 1258 aha->command_cmp = TRUE; 1259 } 1260 1261 aha_outb(aha, CONTROL_REG, RESET_INTR); 1262 1263 if ((intstat & IMB_LOADED) != 0) { 1264 while (aha->cur_inbox->comp_code != AMBI_FREE) { 1265 u_int32_t paddr; 1266 paddr = aha_a24tou(aha->cur_inbox->ccb_addr); 1267 ahadone(aha, 1268 ahaccbptov(aha, paddr), 1269 aha->cur_inbox->comp_code); 1270 aha->cur_inbox->comp_code = AMBI_FREE; 1271 ahanextinbox(aha); 1272 } 1273 } 1274 1275 if ((intstat & SCSI_BUS_RESET) != 0) { 1276 ahareset(aha, /*hardreset*/FALSE); 1277 } 1278 } 1279} 1280 1281static void 1282ahadone(struct aha_softc *aha, struct aha_ccb *accb, aha_mbi_comp_code_t comp_code) 1283{ 1284 union ccb *ccb; 1285 struct ccb_scsiio *csio; 1286 1287 ccb = accb->ccb; 1288 csio = &accb->ccb->csio; 1289 1290 if ((accb->flags & ACCB_ACTIVE) == 0) { 1291 printf("%s: ahadone - Attempt to free non-active ACCB %p\n", 1292 aha_name(aha), (void *)accb); 1293 return; 1294 } 1295 1296 if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 1297 bus_dmasync_op_t op; 1298 1299 if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) 1300 op = BUS_DMASYNC_POSTREAD; 1301 else 1302 op = BUS_DMASYNC_POSTWRITE; 1303 bus_dmamap_sync(aha->buffer_dmat, accb->dmamap, op); 1304 bus_dmamap_unload(aha->buffer_dmat, accb->dmamap); 1305 } 1306 1307 if (accb == aha->recovery_accb) { 1308 /* 1309 * The recovery ACCB does not have a CCB associated 1310 * with it, so short circuit the normal error handling. 1311 * We now traverse our list of pending CCBs and process 1312 * any that were terminated by the recovery CCBs action. 1313 * We also reinstate timeouts for all remaining, pending, 1314 * CCBs. 1315 */ 1316 struct cam_path *path; 1317 struct ccb_hdr *ccb_h; 1318 cam_status error; 1319 1320 /* Notify all clients that a BDR occured */ 1321 error = xpt_create_path(&path, /*periph*/NULL, 1322 cam_sim_path(aha->sim), 1323 accb->hccb.target, 1324 CAM_LUN_WILDCARD); 1325 1326 if (error == CAM_REQ_CMP) 1327 xpt_async(AC_SENT_BDR, path, NULL); 1328 1329 ccb_h = LIST_FIRST(&aha->pending_ccbs); 1330 while (ccb_h != NULL) { 1331 struct aha_ccb *pending_accb; 1332 1333 pending_accb = (struct aha_ccb *)ccb_h->ccb_accb_ptr; 1334 if (pending_accb->hccb.target == accb->hccb.target) { 1335 pending_accb->hccb.ahastat = AHASTAT_HA_BDR; 1336 ccb_h = LIST_NEXT(ccb_h, sim_links.le); 1337 ahadone(aha, pending_accb, AMBI_ERROR); 1338 } else { 1339 ccb_h->timeout_ch = 1340 timeout(ahatimeout, (caddr_t)pending_accb, 1341 (ccb_h->timeout * hz) / 1000); 1342 ccb_h = LIST_NEXT(ccb_h, sim_links.le); 1343 } 1344 } 1345 printf("%s: No longer in timeout\n", aha_name(aha)); 1346 return; 1347 } 1348 1349 untimeout(ahatimeout, accb, ccb->ccb_h.timeout_ch); 1350 1351 switch (comp_code) { 1352 case AMBI_FREE: 1353 printf("%s: ahadone - CCB completed with free status!\n", 1354 aha_name(aha)); 1355 break; 1356 case AMBI_NOT_FOUND: 1357 printf("%s: ahadone - CCB Abort failed to find CCB\n", 1358 aha_name(aha)); 1359 break; 1360 case AMBI_ABORT: 1361 case AMBI_ERROR: 1362 /* An error occured */ 1363 csio->resid = aha_a24tou(accb->hccb.data_len); 1364 switch(accb->hccb.ahastat) { 1365 case AHASTAT_DATARUN_ERROR: 1366 { 1367 if (csio->resid <= 0) { 1368 csio->ccb_h.status = CAM_DATA_RUN_ERR; 1369 break; 1370 } 1371 /* FALLTHROUGH */ 1372 } 1373 case AHASTAT_NOERROR: 1374 csio->scsi_status = accb->hccb.sdstat; 1375 csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 1376 switch(csio->scsi_status) { 1377 case SCSI_STATUS_CHECK_COND: 1378 case SCSI_STATUS_CMD_TERMINATED: 1379 csio->ccb_h.status |= CAM_AUTOSNS_VALID; 1380 /* 1381 * The aha writes the sense data at different 1382 * offsets based on the scsi cmd len 1383 */ 1384 bcopy((caddr_t) &accb->hccb.scsi_cdb + 1385 accb->hccb.cmd_len, 1386 (caddr_t) &csio->sense_data, 1387 accb->hccb.sense_len); 1388 break; 1389 default: 1390 break; 1391 case SCSI_STATUS_OK: 1392 csio->ccb_h.status = CAM_REQ_CMP; 1393 break; 1394 } 1395 break; 1396 case AHASTAT_SELTIMEOUT: 1397 csio->ccb_h.status = CAM_SEL_TIMEOUT; 1398 break; 1399 case AHASTAT_UNEXPECTED_BUSFREE: 1400 csio->ccb_h.status = CAM_UNEXP_BUSFREE; 1401 break; 1402 case AHASTAT_INVALID_PHASE: 1403 csio->ccb_h.status = CAM_SEQUENCE_FAIL; 1404 break; 1405 case AHASTAT_INVALID_ACTION_CODE: 1406 panic("%s: Inavlid Action code", aha_name(aha)); 1407 break; 1408 case AHASTAT_INVALID_OPCODE: 1409 panic("%s: Inavlid CCB Opcode code %x hccb = %p", 1410 aha_name(aha), accb->hccb.opcode, &accb->hccb); 1411 break; 1412 case AHASTAT_LINKED_CCB_LUN_MISMATCH: 1413 /* We don't even support linked commands... */ 1414 panic("%s: Linked CCB Lun Mismatch", aha_name(aha)); 1415 break; 1416 case AHASTAT_INVALID_CCB_OR_SG_PARAM: 1417 panic("%s: Invalid CCB or SG list", aha_name(aha)); 1418 break; 1419 case AHASTAT_HA_SCSI_BUS_RESET: 1420 if ((csio->ccb_h.status & CAM_STATUS_MASK) 1421 != CAM_CMD_TIMEOUT) 1422 csio->ccb_h.status = CAM_SCSI_BUS_RESET; 1423 break; 1424 case AHASTAT_HA_BDR: 1425 if ((accb->flags & ACCB_DEVICE_RESET) == 0) 1426 csio->ccb_h.status = CAM_BDR_SENT; 1427 else 1428 csio->ccb_h.status = CAM_CMD_TIMEOUT; 1429 break; 1430 } 1431 if (csio->ccb_h.status != CAM_REQ_CMP) { 1432 xpt_freeze_devq(csio->ccb_h.path, /*count*/1); 1433 csio->ccb_h.status |= CAM_DEV_QFRZN; 1434 } 1435 if ((accb->flags & ACCB_RELEASE_SIMQ) != 0) 1436 ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1437 ahafreeccb(aha, accb); 1438 xpt_done(ccb); 1439 break; 1440 case AMBI_OK: 1441 /* All completed without incident */ 1442 /* XXX DO WE NEED TO COPY SENSE BYTES HERE???? XXX */ 1443 ccb->ccb_h.status |= CAM_REQ_CMP; 1444 if ((accb->flags & ACCB_RELEASE_SIMQ) != 0) 1445 ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1446 ahafreeccb(aha, accb); 1447 xpt_done(ccb); 1448 break; 1449 } 1450} 1451 1452static int 1453ahareset(struct aha_softc* aha, int hard_reset) 1454{ 1455 struct ccb_hdr *ccb_h; 1456 u_int status; 1457 u_int timeout; 1458 u_int8_t reset_type; 1459 1460 if (hard_reset != 0) 1461 reset_type = HARD_RESET; 1462 else 1463 reset_type = SOFT_RESET; 1464 aha_outb(aha, CONTROL_REG, reset_type); 1465 1466 /* Wait 5sec. for Diagnostic start */ 1467 timeout = 5 * 10000; 1468 while (--timeout) { 1469 status = aha_inb(aha, STATUS_REG); 1470 if ((status & DIAG_ACTIVE) != 0) 1471 break; 1472 DELAY(100); 1473 } 1474 if (timeout == 0) { 1475 PRVERB(("%s: ahareset - Diagnostic Active failed to " 1476 "assert. status = 0x%x\n", aha_name(aha), 1477 status)); 1478 return (ETIMEDOUT); 1479 } 1480 1481 /* Wait 10sec. for Diagnostic end */ 1482 timeout = 10 * 10000; 1483 while (--timeout) { 1484 status = aha_inb(aha, STATUS_REG); 1485 if ((status & DIAG_ACTIVE) == 0) 1486 break; 1487 DELAY(100); 1488 } 1489 if (timeout == 0) { 1490 panic("%s: ahareset - Diagnostic Active failed to drop. " 1491 "status = 0x%x\n", aha_name(aha), status); 1492 return (ETIMEDOUT); 1493 } 1494 1495 /* Wait for the host adapter to become ready or report a failure */ 1496 timeout = 10000; 1497 while (--timeout) { 1498 status = aha_inb(aha, STATUS_REG); 1499 if ((status & (DIAG_FAIL|HA_READY|DATAIN_REG_READY)) != 0) 1500 break; 1501 DELAY(100); 1502 } 1503 if (timeout == 0) { 1504 printf("%s: ahareset - Host adapter failed to come ready. " 1505 "status = 0x%x\n", aha_name(aha), status); 1506 return (ETIMEDOUT); 1507 } 1508 1509 /* If the diagnostics failed, tell the user */ 1510 if ((status & DIAG_FAIL) != 0 1511 || (status & HA_READY) == 0) { 1512 printf("%s: ahareset - Adapter failed diagnostics\n", 1513 aha_name(aha)); 1514 1515 if ((status & DATAIN_REG_READY) != 0) 1516 printf("%s: ahareset - Host Adapter Error " 1517 "code = 0x%x\n", aha_name(aha), 1518 aha_inb(aha, DATAIN_REG)); 1519 return (ENXIO); 1520 } 1521 1522 /* If we've allocated mailboxes, initialize them */ 1523 if (aha->init_level > 4) 1524 ahainitmboxes(aha); 1525 1526 /* If we've attached to the XPT, tell it about the event */ 1527 if (aha->path != NULL) 1528 xpt_async(AC_BUS_RESET, aha->path, NULL); 1529 1530 /* 1531 * Perform completion processing for all outstanding CCBs. 1532 */ 1533 while ((ccb_h = LIST_FIRST(&aha->pending_ccbs)) != NULL) { 1534 struct aha_ccb *pending_accb; 1535 1536 pending_accb = (struct aha_ccb *)ccb_h->ccb_accb_ptr; 1537 pending_accb->hccb.ahastat = AHASTAT_HA_SCSI_BUS_RESET; 1538 ahadone(aha, pending_accb, AMBI_ERROR); 1539 } 1540 1541 return (0); 1542} 1543 1544/* 1545 * Send a command to the adapter. 1546 */ 1547int 1548aha_cmd(struct aha_softc *aha, aha_op_t opcode, u_int8_t *params, 1549 u_int param_len, u_int8_t *reply_data, u_int reply_len, 1550 u_int cmd_timeout) 1551{ 1552 u_int timeout; 1553 u_int status; 1554 u_int intstat; 1555 u_int reply_buf_size; 1556 int s; 1557 int cmd_complete; 1558 1559 /* No data returned to start */ 1560 reply_buf_size = reply_len; 1561 reply_len = 0; 1562 intstat = 0; 1563 cmd_complete = 0; 1564 1565 aha->command_cmp = 0; 1566 /* 1567 * Wait up to 1 sec. for the adapter to become 1568 * ready to accept commands. 1569 */ 1570 timeout = 10000; 1571 while (--timeout) { 1572 1573 status = aha_inb(aha, STATUS_REG); 1574 if ((status & HA_READY) != 0 1575 && (status & CMD_REG_BUSY) == 0) 1576 break; 1577 DELAY(100); 1578 } 1579 if (timeout == 0) { 1580 printf("%s: aha_cmd: Timeout waiting for adapter ready, " 1581 "status = 0x%x\n", aha_name(aha), status); 1582 return (ETIMEDOUT); 1583 } 1584 1585 /* 1586 * Send the opcode followed by any necessary parameter bytes. 1587 */ 1588 aha_outb(aha, COMMAND_REG, opcode); 1589 1590 /* 1591 * Wait for up to 1sec to get the parameter list sent 1592 */ 1593 timeout = 10000; 1594 while (param_len && --timeout) { 1595 DELAY(100); 1596 status = aha_inb(aha, STATUS_REG); 1597 intstat = aha_inb(aha, INTSTAT_REG); 1598 if ((intstat & (INTR_PENDING|CMD_COMPLETE)) 1599 == (INTR_PENDING|CMD_COMPLETE)) { 1600 cmd_complete = 1; 1601 break; 1602 } 1603 if (aha->command_cmp != 0) { 1604 status = aha->latched_status; 1605 cmd_complete = 1; 1606 break; 1607 } 1608 if ((status & DATAIN_REG_READY) != 0) 1609 break; 1610 if ((status & CMD_REG_BUSY) == 0) { 1611 aha_outb(aha, COMMAND_REG, *params++); 1612 param_len--; 1613 } 1614 } 1615 if (timeout == 0) { 1616 printf("%s: aha_cmd: Timeout sending parameters, " 1617 "status = 0x%x\n", aha_name(aha), status); 1618 return (ETIMEDOUT); 1619 } 1620 1621 /* 1622 * For all other commands, we wait for any output data 1623 * and the final comand completion interrupt. 1624 */ 1625 while (cmd_complete == 0 && --cmd_timeout) { 1626 1627 status = aha_inb(aha, STATUS_REG); 1628 intstat = aha_inb(aha, INTSTAT_REG); 1629 if ((intstat & (INTR_PENDING|CMD_COMPLETE)) 1630 == (INTR_PENDING|CMD_COMPLETE)) 1631 break; 1632 1633 if (aha->command_cmp != 0) { 1634 status = aha->latched_status; 1635 break; 1636 } 1637 1638 if ((status & DATAIN_REG_READY) != 0) { 1639 u_int8_t data; 1640 1641 data = aha_inb(aha, DATAIN_REG); 1642 if (reply_len < reply_buf_size) { 1643 *reply_data++ = data; 1644 } else { 1645 printf("%s: aha_cmd - Discarded reply data byte " 1646 "for opcode 0x%x\n", aha_name(aha), 1647 opcode); 1648 } 1649 reply_len++; 1650 } 1651 1652 DELAY(100); 1653 } 1654 if (timeout == 0) { 1655 printf("%s: aha_cmd: Timeout waiting for reply data and " 1656 "command complete.\n%s: status = 0x%x, intstat = 0x%x, " 1657 "reply_len = %d\n", aha_name(aha), aha_name(aha), status, 1658 intstat, reply_len); 1659 return (ETIMEDOUT); 1660 } 1661 1662 /* 1663 * Clear any pending interrupts. Block interrupts so our 1664 * interrupt handler is not re-entered. 1665 */ 1666 s = splcam(); 1667 aha_intr(aha); 1668 splx(s); 1669 1670 /* 1671 * If the command was rejected by the controller, tell the caller. 1672 */ 1673 if ((status & CMD_INVALID) != 0) { 1674 PRVERB(("%s: Invalid Command 0x%x\n", aha_name(aha), opcode)); 1675 /* 1676 * Some early adapters may not recover properly from 1677 * an invalid command. If it appears that the controller 1678 * has wedged (i.e. status was not cleared by our interrupt 1679 * reset above), perform a soft reset. 1680 */ 1681 DELAY(1000); 1682 status = aha_inb(aha, STATUS_REG); 1683 if ((status & (CMD_INVALID|STATUS_REG_RSVD|DATAIN_REG_READY| 1684 CMD_REG_BUSY|DIAG_FAIL|DIAG_ACTIVE)) != 0 1685 || (status & (HA_READY|INIT_REQUIRED)) 1686 != (HA_READY|INIT_REQUIRED)) { 1687 ahareset(aha, /*hard_reset*/FALSE); 1688 } 1689 return (EINVAL); 1690 } 1691 1692 1693 if (param_len > 0) { 1694 /* The controller did not accept the full argument list */ 1695 return (E2BIG); 1696 } 1697 1698 if (reply_len != reply_buf_size) { 1699 /* Too much or too little data received */ 1700 return (EMSGSIZE); 1701 } 1702 1703 /* We were successful */ 1704 return (0); 1705} 1706 1707static int 1708ahainitmboxes(struct aha_softc *aha) 1709{ 1710 int error; 1711 init_24b_mbox_params_t init_mbox; 1712 1713 bzero(aha->in_boxes, sizeof(aha_mbox_in_t) * aha->num_boxes); 1714 bzero(aha->out_boxes, sizeof(aha_mbox_out_t) * aha->num_boxes); 1715 aha->cur_inbox = aha->in_boxes; 1716 aha->last_inbox = aha->in_boxes + aha->num_boxes - 1; 1717 aha->cur_outbox = aha->out_boxes; 1718 aha->last_outbox = aha->out_boxes + aha->num_boxes - 1; 1719 1720 /* Tell the adapter about them */ 1721 init_mbox.num_mboxes = aha->num_boxes; 1722 ahautoa24(aha->mailbox_physbase, init_mbox.base_addr); 1723 error = aha_cmd(aha, AOP_INITIALIZE_MBOX, (u_int8_t *)&init_mbox, 1724 /*parmlen*/sizeof(init_mbox), /*reply_buf*/NULL, 1725 /*reply_len*/0, DEFAULT_CMD_TIMEOUT); 1726 1727 if (error != 0) 1728 printf("ahainitmboxes: Initialization command failed\n"); 1729 return (error); 1730} 1731 1732/* 1733 * Update the XPT's idea of the negotiated transfer 1734 * parameters for a particular target. 1735 */ 1736static void 1737ahafetchtransinfo(struct aha_softc *aha, struct ccb_trans_settings* cts) 1738{ 1739 setup_data_t setup_info; 1740 u_int target; 1741 u_int targ_offset; 1742 u_int sync_period; 1743 int error; 1744 u_int8_t param; 1745 targ_syncinfo_t sync_info; 1746 1747 target = cts->ccb_h.target_id; 1748 targ_offset = (target & 0x7); 1749 1750 /* 1751 * Inquire Setup Information. This command retreives the 1752 * Wide negotiation status for recent adapters as well as 1753 * the sync info for older models. 1754 */ 1755 param = sizeof(setup_info); 1756 error = aha_cmd(aha, AOP_INQUIRE_SETUP_INFO, ¶m, /*paramlen*/1, 1757 (u_int8_t*)&setup_info, sizeof(setup_info), 1758 DEFAULT_CMD_TIMEOUT); 1759 1760 if (error != 0) { 1761 printf("%s: ahafetchtransinfo - Inquire Setup Info Failed\n", 1762 aha_name(aha)); 1763 return; 1764 } 1765 1766 sync_info = setup_info.syncinfo[targ_offset]; 1767 1768 if (sync_info.sync == 0) 1769 cts->sync_offset = 0; 1770 else 1771 cts->sync_offset = sync_info.offset; 1772 1773 cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; 1774 1775 sync_period = 2000 + (500 * sync_info.period); 1776 1777 /* Convert ns value to standard SCSI sync rate */ 1778 if (cts->sync_offset != 0) 1779 cts->sync_period = scsi_calc_syncparam(sync_period); 1780 else 1781 cts->sync_period = 0; 1782 1783 cts->valid = CCB_TRANS_SYNC_RATE_VALID 1784 | CCB_TRANS_SYNC_OFFSET_VALID 1785 | CCB_TRANS_BUS_WIDTH_VALID; 1786 xpt_async(AC_TRANSFER_NEG, cts->ccb_h.path, cts); 1787} 1788 1789static void 1790ahamapmboxes(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1791{ 1792 struct aha_softc* aha; 1793 1794 aha = (struct aha_softc*)arg; 1795 aha->mailbox_physbase = segs->ds_addr; 1796} 1797 1798static void 1799ahamapccbs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1800{ 1801 struct aha_softc* aha; 1802 1803 aha = (struct aha_softc*)arg; 1804 aha->aha_ccb_physbase = segs->ds_addr; 1805} 1806 1807static void 1808ahamapsgs(void *arg, bus_dma_segment_t *segs, int nseg, int error) 1809{ 1810 1811 struct aha_softc* aha; 1812 1813 aha = (struct aha_softc*)arg; 1814 SLIST_FIRST(&aha->sg_maps)->sg_physaddr = segs->ds_addr; 1815} 1816 1817static void 1818ahapoll(struct cam_sim *sim) 1819{ 1820 aha_intr(cam_sim_softc(sim)); 1821} 1822 1823void 1824ahatimeout(void *arg) 1825{ 1826 struct aha_ccb *accb; 1827 union ccb *ccb; 1828 struct aha_softc *aha; 1829 int s; 1830 u_int32_t paddr; 1831 1832 accb = (struct aha_ccb *)arg; 1833 ccb = accb->ccb; 1834 aha = (struct aha_softc *)ccb->ccb_h.ccb_aha_ptr; 1835 xpt_print_path(ccb->ccb_h.path); 1836 printf("CCB %p - timed out\n", (void *)accb); 1837 1838 s = splcam(); 1839 1840 if ((accb->flags & ACCB_ACTIVE) == 0) { 1841 xpt_print_path(ccb->ccb_h.path); 1842 printf("CCB %p - timed out CCB already completed\n", 1843 (void *)accb); 1844 splx(s); 1845 return; 1846 } 1847 1848 /* 1849 * In order to simplify the recovery process, we ask the XPT 1850 * layer to halt the queue of new transactions and we traverse 1851 * the list of pending CCBs and remove their timeouts. This 1852 * means that the driver attempts to clear only one error 1853 * condition at a time. In general, timeouts that occur 1854 * close together are related anyway, so there is no benefit 1855 * in attempting to handle errors in parrallel. Timeouts will 1856 * be reinstated when the recovery process ends. 1857 */ 1858 if ((accb->flags & ACCB_DEVICE_RESET) == 0) { 1859 struct ccb_hdr *ccb_h; 1860 1861 if ((accb->flags & ACCB_RELEASE_SIMQ) == 0) { 1862 xpt_freeze_simq(aha->sim, /*count*/1); 1863 accb->flags |= ACCB_RELEASE_SIMQ; 1864 } 1865 1866 ccb_h = LIST_FIRST(&aha->pending_ccbs); 1867 while (ccb_h != NULL) { 1868 struct aha_ccb *pending_accb; 1869 1870 pending_accb = (struct aha_ccb *)ccb_h->ccb_accb_ptr; 1871 untimeout(ahatimeout, pending_accb, ccb_h->timeout_ch); 1872 ccb_h = LIST_NEXT(ccb_h, sim_links.le); 1873 } 1874 } 1875 1876 if ((accb->flags & ACCB_DEVICE_RESET) != 0 1877 || aha->cur_outbox->action_code != AMBO_FREE) { 1878 /* 1879 * Try a full host adapter/SCSI bus reset. 1880 * We do this only if we have already attempted 1881 * to clear the condition with a BDR, or we cannot 1882 * attempt a BDR for lack of mailbox resources. 1883 */ 1884 ccb->ccb_h.status = CAM_CMD_TIMEOUT; 1885 ahareset(aha, /*hardreset*/TRUE); 1886 printf("%s: No longer in timeout\n", aha_name(aha)); 1887 } else { 1888 /* 1889 * Send a Bus Device Reset message: 1890 * The target that is holding up the bus may not 1891 * be the same as the one that triggered this timeout 1892 * (different commands have different timeout lengths), 1893 * but we have no way of determining this from our 1894 * timeout handler. Our strategy here is to queue a 1895 * BDR message to the target of the timed out command. 1896 * If this fails, we'll get another timeout 2 seconds 1897 * later which will attempt a bus reset. 1898 */ 1899 accb->flags |= ACCB_DEVICE_RESET; 1900 ccb->ccb_h.timeout_ch = timeout(ahatimeout, (caddr_t)accb, 2 * hz); 1901 aha->recovery_accb->hccb.opcode = INITIATOR_BUS_DEV_RESET; 1902 1903 /* No Data Transfer */ 1904 aha->recovery_accb->hccb.datain = TRUE; 1905 aha->recovery_accb->hccb.dataout = TRUE; 1906 aha->recovery_accb->hccb.ahastat = 0; 1907 aha->recovery_accb->hccb.sdstat = 0; 1908 aha->recovery_accb->hccb.target = ccb->ccb_h.target_id; 1909 1910 /* Tell the adapter about this command */ 1911 paddr = ahaccbvtop(aha, aha->recovery_accb); 1912 ahautoa24(paddr, aha->cur_outbox->ccb_addr); 1913 aha->cur_outbox->action_code = AMBO_START; 1914 aha_outb(aha, COMMAND_REG, AOP_START_MBOX); 1915 ahanextoutbox(aha); 1916 } 1917 1918 splx(s); 1919} 1920