static int acd_attach(device_t dev) { struct acd_softc *cdp; if (!(cdp = malloc(sizeof(struct acd_softc), M_ACD, M_NOWAIT | M_ZERO))) { device_printf(dev, "out of memory\n"); return ENOMEM; } cdp->block_size = 2048; device_set_ivars(dev, cdp); ata_setmode(dev); ata_controlcmd(dev, ATA_DEVICE_RESET, 0, 0, 0); acd_get_cap(dev); g_post_event(acd_geom_attach, dev, M_WAITOK, NULL); /* announce we are here */ acd_describe(dev); return 0; }
int acdattach(struct atapi *ata, int unit, struct atapi_params *ap, int debug) { struct acd *cdp; struct atapires result; struct changer *chp; int i, count; if (acdnlun >= NUNIT) { printf("wcd: too many units\n"); return 0; } if (!atapi_request_immediate) { printf("wcd: configuration error, ATAPI code not present!\n"); return 0; } if ((cdp = acd_init_lun(ata, unit, ap, acdnlun, NULL)) == NULL) { printf("wcd: out of memory\n"); return 0; } acdtab[acdnlun] = cdp; if (debug) { cdp->flags |= F_DEBUG; atapi_dump(cdp->ata->ctrlr, cdp->lun, "info", ap, sizeof(*ap)); } /* Get drive capabilities, some drives needs this repeated */ for (count = 0 ; count < 5 ; count++) { result = atapi_request_immediate(ata, unit, ATAPI_MODE_SENSE, 0, ATAPI_CDROM_CAP_PAGE, 0, 0, 0, 0, sizeof(cdp->cap)>>8, sizeof(cdp->cap), 0, 0, 0, 0, 0, 0, 0, (char *)&cdp->cap, sizeof(cdp->cap)); if (result.code == 0 || result.code == RES_UNDERRUN) break; } /* Some drives have shorter capabilities page. */ if (result.code == RES_UNDERRUN) result.code = 0; if (result.code == 0) { cdp->cap.max_speed = ntohs(cdp->cap.max_speed); cdp->cap.max_vol_levels = ntohs(cdp->cap.max_vol_levels); cdp->cap.buf_size = ntohs(cdp->cap.buf_size); cdp->cap.cur_speed = ntohs(cdp->cap.cur_speed); acd_describe(cdp); if (cdp->flags & F_DEBUG) atapi_dump(cdp->ata->ctrlr, cdp->lun, "cap", &cdp->cap, sizeof(cdp->cap)); } /* If this is a changer device, allocate the neeeded lun's */ if (cdp->cap.mech == MST_MECH_CHANGER) { char string[16]; struct acd *tmpcdp = cdp; chp = malloc(sizeof(struct changer), M_TEMP, M_NOWAIT | M_ZERO); if (chp == NULL) { printf("wcd: out of memory\n"); return 0; } result = atapi_request_immediate(ata, unit, ATAPI_MECH_STATUS, 0, 0, 0, 0, 0, 0, 0, sizeof(struct changer)>>8, sizeof(struct changer), 0, 0, 0, 0, 0, 0, (char *)chp, sizeof(struct changer)); if (cdp->flags & F_DEBUG) { printf("result.code=%d curr=%02x slots=%d len=%d\n", result.code, chp->current_slot, chp->slots, htons(chp->table_length)); } if (result.code == RES_UNDERRUN) result.code = 0; if (result.code == 0) { chp->table_length = htons(chp->table_length); for (i = 0; i < chp->slots && acdnlun < NUNIT; i++) { if (i > 0) { tmpcdp = acd_init_lun(ata, unit, ap, acdnlun, cdp->device_stats); if (!tmpcdp) { printf("wcd: out of memory\n"); return 0; } } tmpcdp->slot = i; tmpcdp->changer_info = chp; printf("wcd%d: changer slot %d %s\n", acdnlun, i, (chp->slot[i].present ? "disk present" : "no disk")); acdtab[acdnlun++] = tmpcdp; } if (acdnlun >= NUNIT) { printf("wcd: too many units\n"); return 0; } } sprintf(string, "wcd%d-", cdp->lun); devstat_add_entry(cdp->device_stats, string, tmpcdp->lun, DEV_BSIZE, DEVSTAT_NO_ORDERED_TAGS, DEVSTAT_TYPE_CDROM | DEVSTAT_TYPE_IF_IDE, DEVSTAT_PRIORITY_CD); }