atapi-cam.c revision 101606
1/*- 2 * Copyright (c) 2001,2002 Thomas Quinot <thomas@cuivre.fr.eu.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $FreeBSD: head/sys/dev/ata/atapi-cam.c 101606 2002-08-09 20:54:06Z sos $ 29 */ 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/bus.h> 34#include <sys/devicestat.h> 35#include <sys/kernel.h> 36#include <sys/malloc.h> 37#include <sys/ata.h> 38#include <machine/bus.h> 39 40#include <cam/cam.h> 41#include <cam/cam_ccb.h> 42#include <cam/cam_periph.h> 43#include <cam/cam_sim.h> 44#include <cam/cam_xpt_sim.h> 45#include <cam/cam_debug.h> 46#include <cam/scsi/scsi_all.h> 47 48#include <dev/ata/ata-all.h> 49#include <dev/ata/atapi-all.h> 50 51/* hardware command descriptor block */ 52struct atapi_hcb { 53 struct atapi_xpt_softc *softc; 54 int unit; 55 int bus; 56 int target; 57 int lun; 58 union ccb *ccb; 59 u_int8_t cmd[CAM_MAX_CDBLEN]; 60 int lags; 61#define DOING_AUTOSENSE 1 62 63 char *dxfer_alloc; 64 TAILQ_ENTRY(atapi_hcb) chain; 65}; 66 67/* private data associated with an ATA bus */ 68struct atapi_xpt_softc { 69 struct ata_channel *ata_ch; 70 struct cam_path *path; 71 struct cam_sim *sim; 72 int flags; 73#define BUS_REGISTERED 0x01 74#define RESOURCE_SHORTAGE 0x02 75 76 TAILQ_HEAD(,atapi_hcb) pending_hcbs; 77 LIST_ENTRY(atapi_xpt_softc) chain; 78}; 79 80static LIST_HEAD(,atapi_xpt_softc) all_buses = LIST_HEAD_INITIALIZER(all_buses); 81 82/* CAM XPT methods */ 83static void atapi_action(struct cam_sim *, union ccb *); 84static void atapi_action1(struct cam_sim *, union ccb *); 85static void atapi_poll(struct cam_sim *); 86static void atapi_async(void *, u_int32_t, struct cam_path *, void *); 87static void atapi_async1(void *, u_int32_t, struct cam_path *, void *); 88static int atapi_cb(struct atapi_request *); 89 90/* internal functions */ 91static void setup_dev(struct atapi_xpt_softc *, struct ata_device *); 92static void setup_async_cb(struct atapi_xpt_softc *, uint32_t); 93static void cam_rescan_callback(struct cam_periph *, union ccb *); 94static void cam_rescan(struct cam_sim *); 95static void free_hcb_and_ccb_done(struct atapi_hcb *, u_int32_t); 96static struct atapi_hcb *allocate_hcb(struct atapi_xpt_softc *, int, int, union ccb *); 97static void free_hcb(struct atapi_hcb *hcb); 98static void free_softc(struct atapi_xpt_softc *scp); 99static struct ata_device *get_ata_device(struct atapi_xpt_softc *scp, int id); 100 101static MALLOC_DEFINE(M_ATACAM, "ATA CAM transport", "ATA driver CAM-XPT layer"); 102 103void 104atapi_cam_attach_bus(struct ata_channel *ata_ch) 105{ 106 struct atapi_xpt_softc *scp = NULL; 107 struct cam_devq *devq = NULL; 108 struct cam_sim *sim = NULL; 109 struct cam_path *path = NULL; 110 int unit; 111 112 LIST_FOREACH(scp, &all_buses, chain) { 113 if (scp->ata_ch == ata_ch) 114 return; 115 } 116 117 if ((scp = malloc(sizeof(struct atapi_xpt_softc), 118 M_ATACAM, M_NOWAIT | M_ZERO)) == NULL) 119 goto error; 120 121 scp->ata_ch = ata_ch; 122 TAILQ_INIT(&scp->pending_hcbs); 123 LIST_INSERT_HEAD(&all_buses, scp, chain); 124 unit = device_get_unit(ata_ch->dev); 125 126 if ((devq = cam_simq_alloc(16)) == NULL) 127 goto error; 128 129 if ((sim = cam_sim_alloc(atapi_action, atapi_poll, "ata", 130 (void *)scp, unit, 1, 1, devq)) == NULL) { 131 cam_simq_free(devq); 132 goto error; 133 } 134 scp->sim = sim; 135 136 if (xpt_bus_register(sim, 0) != CAM_SUCCESS) { 137 goto error; 138 } 139 scp->flags |= BUS_REGISTERED; 140 141 if (xpt_create_path(&path, /*periph*/ NULL, 142 cam_sim_path(sim), CAM_TARGET_WILDCARD, 143 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 144 goto error; 145 } 146 scp->path = path; 147 148#ifdef CAMDEBUG 149 xpt_print_path(path); 150 printf("Registered SIM for ata%d\n", unit); 151#endif 152 153 setup_async_cb(scp, AC_LOST_DEVICE); 154 155 if (ata_ch->devices & ATA_ATAPI_MASTER) 156 setup_dev(scp, &ata_ch->device[MASTER]); 157 if (ata_ch->devices & ATA_ATAPI_SLAVE) 158 setup_dev(scp, &ata_ch->device[SLAVE]); 159 160 cam_rescan(sim); 161 return; 162 163error: 164 free_softc(scp); 165} 166 167void 168atapi_cam_detach_bus(struct ata_channel *ata_ch) 169{ 170 struct atapi_xpt_softc *scp; 171 172 LIST_FOREACH(scp, &all_buses, chain) { 173 if (scp->ata_ch == ata_ch) 174 free_softc(scp); 175 } 176} 177 178static void 179setup_dev(struct atapi_xpt_softc *scp, struct ata_device *atp) 180{ 181 if (atp->driver == NULL) { 182 ata_set_name(atp, "atapicam", 183 2 * device_get_unit(atp->channel->dev) + 184 (atp->unit == ATA_MASTER) ? 0 : 1); 185 atp->driver = (void *)scp; 186 } 187} 188 189static void 190setup_async_cb(struct atapi_xpt_softc *scp, uint32_t events) 191{ 192 struct ccb_setasync csa; 193 194 xpt_setup_ccb(&csa.ccb_h, scp->path, /*priority*/ 5); 195 csa.ccb_h.func_code = XPT_SASYNC_CB; 196 csa.event_enable = events; 197 csa.callback = &atapi_async; 198 csa.callback_arg = scp->sim; 199 xpt_action((union ccb *) &csa); 200} 201 202static void 203atapi_action(struct cam_sim *sim, union ccb *ccb) 204{ 205 int s = splcam(); 206 207 atapi_action1(sim, ccb); 208 splx(s); 209} 210 211static void 212atapi_action1(struct cam_sim *sim, union ccb *ccb) 213{ 214 struct atapi_xpt_softc *softc = (struct atapi_xpt_softc*)cam_sim_softc(sim); 215 struct ccb_hdr *ccb_h = &ccb->ccb_h; 216 struct atapi_hcb *hcb = NULL; 217 int unit = cam_sim_unit(sim); 218 int bus = cam_sim_bus(sim); 219 int len; 220 char *buf; 221 222 switch (ccb_h->func_code) { 223 case XPT_PATH_INQ: { 224 struct ccb_pathinq *cpi = &ccb->cpi; 225 226 cpi->version_num = 1; 227 cpi->hba_inquiry = 0; 228 cpi->hba_misc = 0; 229 cpi->hba_eng_cnt = 0; 230 bzero(cpi->vuhba_flags, sizeof(cpi->vuhba_flags)); 231 cpi->max_target = 1; 232 cpi->max_lun = 7; 233 cpi->async_flags = 0; 234 cpi->hpath_id = 0; 235 cpi->initiator_id = 7; 236 strncpy(cpi->sim_vid, "ATAPI-SIM", sizeof(cpi->sim_vid)); 237 strncpy(cpi->hba_vid, "ATAPI", sizeof(cpi->hba_vid)); 238 strncpy(cpi->dev_name, cam_sim_name(sim), sizeof cpi->dev_name); 239 cpi->unit_number = cam_sim_unit(sim); 240 cpi->bus_id = cam_sim_bus(sim); 241 if (softc->ata_ch && ccb_h->target_id >= 0) { 242 switch (softc->ata_ch->device[ccb_h->target_id].mode) { 243 case ATA_PIO1: 244 cpi->base_transfer_speed = 5200; 245 break; 246 case ATA_PIO2: 247 cpi->base_transfer_speed = 7000; 248 break; 249 case ATA_PIO3: 250 cpi->base_transfer_speed = 11000; 251 break; 252 case ATA_PIO4: 253 case ATA_DMA: 254 case ATA_WDMA2: 255 cpi->base_transfer_speed = 16000; 256 break; 257 case ATA_UDMA2: 258 cpi->base_transfer_speed = 33000; 259 break; 260 case ATA_UDMA4: 261 cpi->base_transfer_speed = 66000; 262 break; 263 case ATA_UDMA5: 264 cpi->base_transfer_speed = 100000; 265 break; 266 case ATA_UDMA6: 267 cpi->base_transfer_speed = 133000; 268 break; 269 default: cpi->base_transfer_speed = 3300; 270 } 271 } 272 ccb->ccb_h.status = CAM_REQ_CMP; 273 xpt_done(ccb); 274 return; 275 } 276 277 case XPT_RESET_DEV: 278 /* should reset the device */ 279#ifdef CAMDEBUG 280 xpt_print_path(ccb->ccb_h.path); 281 printf("dev reset"); 282#endif 283 ccb->ccb_h.status = CAM_REQ_CMP; 284 xpt_done(ccb); 285 return; 286 287 case XPT_RESET_BUS: 288 /* should reset the ATA bus */ 289#ifdef CAMDEBUG 290 xpt_print_path(ccb->ccb_h.path); 291 printf("bus reset"); 292#endif 293 ccb->ccb_h.status = CAM_REQ_CMP; 294 xpt_done(ccb); 295 return; 296 297 case XPT_SET_TRAN_SETTINGS: 298 /* ignore these, we're not doing SCSI here */ 299 ccb->ccb_h.status = CAM_REQ_CMP; 300 xpt_done(ccb); 301 return; 302 303 case XPT_GET_TRAN_SETTINGS: { 304 struct ccb_trans_settings *cts = &ccb->cts; 305 306 cts->flags |= 307 (CCB_TRANS_SYNC_RATE_VALID | CCB_TRANS_SYNC_OFFSET_VALID | 308 CCB_TRANS_BUS_WIDTH_VALID | CCB_TRANS_DISC_VALID | 309 CCB_TRANS_TQ_VALID); 310 cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 311 cts->sync_period = 0; 312 cts->sync_offset = 0; 313 cts->bus_width = 8; 314 ccb->ccb_h.status = CAM_REQ_CMP; 315 xpt_done(ccb); 316 return; 317 } 318 319 case XPT_CALC_GEOMETRY: { 320 struct ccb_calc_geometry *ccg; 321 unsigned int size_mb; 322 unsigned int secs_per_cylinder; 323 int extended; 324 325 ccg = &ccb->ccg; 326 size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size); 327 extended = 1; 328 329 if (size_mb > 1024 && extended) { 330 ccg->heads = 255; 331 ccg->secs_per_track = 63; 332 } else { 333 ccg->heads = 64; 334 ccg->secs_per_track = 32; 335 } 336 secs_per_cylinder = ccg->heads * ccg->secs_per_track; 337 ccg->cylinders = ccg->volume_size / secs_per_cylinder; 338 ccb->ccb_h.status = CAM_REQ_CMP; 339 xpt_done(ccb); 340 return; 341 } 342 343 case XPT_SCSI_IO: { 344 struct ccb_scsiio *csio = &ccb->csio; 345 int tid = ccb_h->target_id, lid = ccb_h->target_lun; 346 struct ata_device *dev = get_ata_device(softc, tid); 347 348#ifdef CAMDEBUG 349 char cdb_str[(SCSI_MAX_CDBLEN * 3) + 1]; 350 351 printf("XPT_SCSI_IO (b%d u%d t%d l%d)\n", bus, unit, tid, lid); 352#endif 353 /* check that this request was not aborted already */ 354 if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) { 355#ifdef CAMDEBUG 356 printf("Already in progress\n"); 357#endif 358 xpt_done(ccb); 359 return; 360 } 361 if (dev == NULL) { 362#ifdef CAMDEBUG 363 printf("Invalid target %d\n", tid); 364#endif 365 ccb_h->status = CAM_TID_INVALID; 366 xpt_done(ccb); 367 return; 368 } 369 if (lid > 0) { 370#ifdef CAMDEBUG 371 printf("Invalid LUN %d\n", lid); 372#endif 373 ccb_h->status = CAM_LUN_INVALID; 374 xpt_done(ccb); 375 return; 376 } 377 if ((ccb_h->flags & CAM_SCATTER_VALID)) { 378 /* scatter-gather not supported */ 379 xpt_print_path(ccb_h->path); 380 printf("ATAPI-CAM does not support scatter-gather yet!\n"); 381 break; 382 } 383 if ((hcb = allocate_hcb(softc, unit, bus, ccb)) == NULL) 384 goto action_oom; 385 386 ccb_h->status |= CAM_SIM_QUEUED; 387 388 bcopy((ccb_h->flags & CAM_CDB_POINTER) ? 389 csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes, 390 hcb->cmd, csio->cdb_len); 391#ifdef CAMDEBUG 392 printf("hcb@%p: %s\n", 393 hcb, scsi_cdb_string(hcb->cmd, cdb_str, sizeof(cdb_str))); 394#endif 395 396 len = csio->dxfer_len; 397 buf = csio->data_ptr; 398 399 /* some SCSI commands require special processing */ 400 switch (hcb->cmd[0]) { 401 case INQUIRY: { 402 /* 403 * many ATAPI devices seem to report more than 404 * SHORT_INQUIRY_LENGTH bytes of available INQUIRY 405 * information, but respond with some incorrect condition 406 * when actually asked for it, so we are going to pretend 407 * that only SHORT_INQUIRY_LENGTH are expected, anyway. 408 */ 409 struct scsi_inquiry *inq = (struct scsi_inquiry *) &hcb->cmd[0]; 410 411 if (inq->byte2 == 0 && inq->page_code == 0 && 412 inq->length > SHORT_INQUIRY_LENGTH) { 413 bzero(buf, len); 414 len = inq->length = SHORT_INQUIRY_LENGTH; 415 } 416 break; 417 } 418 case MODE_SELECT_6: 419 /* FALLTHROUGH */ 420 421 case MODE_SENSE_6: 422 /* 423 * not supported by ATAPI/MMC devices (per SCSI MMC spec) 424 * translate to _10 equivalent. 425 * (actually we should do this only if we have tried 426 * MODE_foo_6 and received ILLEGAL_REQUEST or 427 * INVALID COMMAND OPERATION CODE) 428 * alternative fix: behave like a honest CAM transport, 429 * do not muck with CDB contents, and change scsi_cd to 430 * always use MODE_SENSE_10 in cdgetmode(), or let scsi_cd 431 * know that this specific unit is an ATAPI/MMC one, 432 * and in /that case/ use MODE_SENSE_10 433 */ 434 435#ifdef CAMDEBUG 436 xpt_print_path(ccb_h->path); 437 printf("Translating %s into _10 equivalent\n", 438 (hcb->cmd[0] == MODE_SELECT_6) ? 439 "MODE_SELECT_6" : "MODE_SENSE_6"); 440#endif 441 hcb->cmd[0] |= 0x40; 442 hcb->cmd[6] = 0; 443 hcb->cmd[7] = 0; 444 hcb->cmd[8] = hcb->cmd[4]; 445 hcb->cmd[9] = hcb->cmd[5]; 446 hcb->cmd[4] = 0; 447 hcb->cmd[5] = 0; 448 break; 449 450 case READ_6: 451 /* FALLTHROUGH */ 452 453 case WRITE_6: 454#ifdef CAMDEBUG 455 xpt_print_path(ccb_h->path); 456 printf("Translating %s into _10 equivalent\n", 457 (hcb->cmd[0] == READ_6) ? "READ_6" : "WRITE_6"); 458#endif 459 hcb->cmd[0] |= 0x20; 460 hcb->cmd[9] = hcb->cmd[5]; 461 hcb->cmd[8] = hcb->cmd[4]; 462 hcb->cmd[7] = 0; 463 hcb->cmd[6] = 0; 464 hcb->cmd[5] = hcb->cmd[3]; 465 hcb->cmd[4] = hcb->cmd[2]; 466 hcb->cmd[3] = hcb->cmd[1] & 0x1f; 467 hcb->cmd[2] = 0; 468 hcb->cmd[1] = 0; 469 break; 470 } 471 472 if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN && (len & 1)) { 473 /* ATA always transfers an even number of bytes */ 474 if (!(buf = hcb->dxfer_alloc = malloc(++len, M_ATACAM, 475 M_NOWAIT | M_ZERO))) 476 goto action_oom; 477 } 478 TAILQ_INSERT_TAIL(&softc->pending_hcbs, hcb, chain); 479 if (atapi_queue_cmd(dev, hcb->cmd, buf, len, 480 (((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN) ? 481 ATPR_F_READ : 0) | ATPR_F_QUIET, 482 ccb_h->timeout, atapi_cb, (void *)hcb) == 0) 483 return; 484 break; 485 } 486 487 default: 488 printf("atapi-cam: unsupported function code 0x%02x\n", 489 ccb_h->func_code); 490 ccb_h->status = CAM_REQ_INVALID; 491 xpt_done(ccb); 492 return; 493 } 494 495action_oom: 496 if (hcb != NULL) 497 free_hcb(hcb); 498 xpt_print_path(ccb_h->path); 499 printf("Out of memory: freezing queue."); 500 softc->flags |= RESOURCE_SHORTAGE; 501 xpt_freeze_simq(sim, /*count*/ 1); 502 ccb_h->status = CAM_REQUEUE_REQ; 503 xpt_done(ccb); 504} 505 506static void 507atapi_poll(struct cam_sim *sim) 508{ 509 /* do nothing - we do not actually service any interrupts */ 510 printf("atapi_poll called!\n"); 511} 512 513int 514atapi_cb(struct atapi_request *req) 515{ 516 int s = splcam(); 517 struct atapi_hcb *hcb = (struct atapi_hcb *) req->driver; 518 struct ccb_scsiio *csio = &hcb->ccb->csio; 519 int hcb_status = req->result; 520 521#ifdef CAMDEBUG 522 printf("atapi_cb: hcb@%p status = %02x: (sk = %02x%s%s%s)\n", 523 hcb, hcb_status, hcb_status >> 4, 524 (hcb_status & 4) ? " ABRT" : "", 525 (hcb_status & 2) ? " EOM" : "", 526 (hcb_status & 1) ? " ILI" : ""); 527 printf(" %s: cmd %02x - sk=%02x asc=%02x ascq=%02x\n", 528 req->device->name, req->ccb[0], req->sense.sense_key, 529 req->sense.asc, req->sense.ascq); 530#endif 531 if (hcb_status != 0) { 532 hcb->ccb->csio.scsi_status = SCSI_STATUS_CHECK_COND; 533 if ((hcb->ccb->ccb_h.flags & CAM_DIS_AUTOSENSE) == 0) { 534 hcb->ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 535 bcopy((void *)&req->sense, (void *)&csio->sense_data, 536 sizeof(struct atapi_reqsense)); 537 } 538 free_hcb_and_ccb_done(hcb, CAM_SCSI_STATUS_ERROR); 539 } 540 else { 541 if (((hcb->ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) && 542 hcb->dxfer_alloc != NULL) 543 bcopy(hcb->dxfer_alloc, csio->data_ptr, csio->dxfer_len); 544 hcb->ccb->csio.scsi_status = SCSI_STATUS_OK; 545 free_hcb_and_ccb_done(hcb, CAM_REQ_CMP); 546 } 547 splx(s); 548 return 0; 549} 550 551static void 552free_hcb_and_ccb_done(struct atapi_hcb *hcb, u_int32_t status) 553{ 554 struct atapi_xpt_softc *softc = hcb->softc; 555 union ccb *ccb = hcb->ccb; 556 557 if (hcb != NULL) { 558 /* we're about to free a hcb, so the shortage has ended */ 559 if (softc->flags & RESOURCE_SHORTAGE) { 560 softc->flags &= ~RESOURCE_SHORTAGE; 561 status |= CAM_RELEASE_SIMQ; 562 } 563 free_hcb(hcb); 564 } 565 ccb->ccb_h.status = 566 status | (ccb->ccb_h.status & ~(CAM_STATUS_MASK | CAM_SIM_QUEUED)); 567 xpt_done(ccb); 568} 569 570static void 571atapi_async(void *callback_arg, u_int32_t code, 572 struct cam_path *path, void *arg) 573{ 574 int s = splcam(); 575 576 atapi_async1(callback_arg, code, path, arg); 577 splx(s); 578} 579 580static void 581atapi_async1(void *callback_arg, u_int32_t code, 582 struct cam_path* path, void *arg) 583{ 584 struct atapi_xpt_softc *softc; 585 struct cam_sim *sim; 586 int targ; 587 588 sim = (struct cam_sim *) callback_arg; 589 softc = (struct atapi_xpt_softc *) cam_sim_softc(sim); 590 switch (code) { 591 case AC_LOST_DEVICE: 592 targ = xpt_path_target_id(path); 593 xpt_print_path(path); 594 if (targ == -1) 595 printf("Lost host adapter\n"); 596 else 597 printf("Lost target %d???\n", targ); 598 break; 599 600 default: 601 break; 602 } 603} 604 605static void 606cam_rescan_callback(struct cam_periph *periph, union ccb *ccb) 607{ 608#ifdef CAMDEBUG 609 xpt_print_path(ccb->ccb_h.path); 610 if (ccb->ccb_h.status != CAM_REQ_CMP) 611 printf("Rescan failed, 0x%04x\n", ccb->ccb_h.status); 612 else 613 printf("rescan succeeded\n"); 614#endif 615 xpt_free_path(ccb->ccb_h.path); 616 free(ccb, M_ATACAM); 617} 618 619static void 620cam_rescan(struct cam_sim *sim) 621{ 622 struct cam_path *path; 623 union ccb *ccb = malloc(sizeof(union ccb), M_ATACAM, M_WAITOK | M_ZERO); 624 625#ifdef CAMDEBUG 626 xpt_print_path(cam_sim_path(sim)); 627 printf ("rescanning ATAPI bus.\n"); 628#endif 629 if (xpt_create_path(&path, xpt_periph, cam_sim_path(sim), 630 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) 631 return; 632 633 xpt_setup_ccb(&ccb->ccb_h, path, 5/*priority (low)*/); 634 ccb->ccb_h.func_code = XPT_SCAN_BUS; 635 ccb->ccb_h.cbfcnp = cam_rescan_callback; 636 ccb->crcn.flags = CAM_FLAG_NONE; 637 xpt_action(ccb); 638 /* scan is in progress now */ 639} 640 641static struct atapi_hcb * 642allocate_hcb(struct atapi_xpt_softc *softc, int unit, int bus, union ccb *ccb) 643{ 644 struct atapi_hcb *hcb = (struct atapi_hcb *) 645 malloc(sizeof(struct atapi_hcb), M_ATACAM, M_NOWAIT | M_ZERO); 646 647 if (hcb != NULL) { 648 hcb->softc = softc; 649 hcb->unit = unit; 650 hcb->bus = bus; 651 hcb->ccb = ccb; 652 } 653 return hcb; 654} 655 656static void 657free_hcb(struct atapi_hcb *hcb) 658{ 659 TAILQ_REMOVE(&hcb->softc->pending_hcbs, hcb, chain); 660 if (hcb->dxfer_alloc != NULL) 661 free(hcb->dxfer_alloc, M_ATACAM); 662 free(hcb, M_ATACAM); 663} 664 665static void 666free_softc(struct atapi_xpt_softc *scp) 667{ 668 struct atapi_hcb *hcb; 669 670 if (scp != NULL) { 671 TAILQ_FOREACH(hcb, &scp->pending_hcbs, chain) { 672 free_hcb_and_ccb_done(hcb, CAM_UNREC_HBA_ERROR); 673 } 674 if (scp->path != NULL) { 675 setup_async_cb(scp, 0); 676 xpt_free_path(scp->path); 677 } 678 if ((scp->flags & BUS_REGISTERED) != 0) { 679 if (xpt_bus_deregister(cam_sim_path(scp->sim)) == CAM_REQ_CMP) 680 scp->flags &= ~BUS_REGISTERED; 681 } 682 if (scp->sim != NULL) { 683 if ((scp->flags & BUS_REGISTERED) == 0) 684 cam_sim_free(scp->sim, /*free_devq*/TRUE); 685 else 686 printf("Can't free %s SIM (still registered)\n", 687 cam_sim_name(scp->sim)); 688 } 689 LIST_REMOVE(scp, chain); 690 free(scp, M_ATACAM); 691 } 692} 693 694static struct ata_device * 695get_ata_device(struct atapi_xpt_softc *scp, int id) 696{ 697 int role = ATA_ATAPI_MASTER; 698 699 switch (id) { 700 case 1: 701 role = ATA_ATAPI_SLAVE; 702 /* FALLTHROUGH */ 703 704 case 0: 705 if (scp->ata_ch->devices & role) 706 return &scp->ata_ch->device[id]; 707 /* FALLTHROUGH */ 708 709 default: 710 return NULL; 711 } 712} 713