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