void atapiscsi_attach(struct device *parent, struct device *self, void *aux) { struct atapiscsi_softc *as = (struct atapiscsi_softc *)self; struct ata_atapi_attach *aa_link = aux; struct scsibus_attach_args saa; struct ata_drive_datas *drvp = aa_link->aa_drv_data; struct channel_softc *chp = drvp->chnl_softc; struct ataparams *id = &drvp->id; struct device *child; extern struct scsi_iopool wdc_xfer_iopool; printf("\n"); /* Initialize shared data. */ scsi_init(); #ifdef WDCDEBUG if (chp->wdc->sc_dev.dv_cfdata->cf_flags & WDC_OPTION_PROBE_VERBOSE) wdcdebug_atapi_mask |= DEBUG_PROBE; #endif as->chp = chp; as->drive = drvp->drive; as->sc_adapterlink.adapter_softc = as; as->sc_adapterlink.adapter_target = 7; as->sc_adapterlink.adapter_buswidth = 2; as->sc_adapterlink.adapter = &atapiscsi_switch; as->sc_adapterlink.luns = 1; as->sc_adapterlink.openings = 1; as->sc_adapterlink.flags = SDEV_ATAPI; as->sc_adapterlink.pool = &wdc_xfer_iopool; strlcpy(drvp->drive_name, as->sc_dev.dv_xname, sizeof(drvp->drive_name)); drvp->cf_flags = as->sc_dev.dv_cfdata->cf_flags; wdc_probe_caps(drvp, id); WDCDEBUG_PRINT( ("general config %04x capabilities %04x ", id->atap_config, id->atap_capabilities1), DEBUG_PROBE); #if (NERRS_MAX > 2) drvp->n_dmaerrs = NERRS_MAX - 2; #else drvp->n_dmaerrs = 0; #endif drvp->drive_flags |= DRIVE_DEVICE_RESET; /* Tape drives do funny DSC stuff */ if (ATAPI_CFG_TYPE(id->atap_config) == ATAPI_CFG_TYPE_SEQUENTIAL) drvp->atapi_cap |= ACAP_DSC; if ((id->atap_config & ATAPI_CFG_CMD_MASK) == ATAPI_CFG_CMD_16) drvp->atapi_cap |= ACAP_LEN; drvp->atapi_cap |= (id->atap_config & ATAPI_CFG_DRQ_MASK); WDCDEBUG_PRINT(("driver caps %04x\n", drvp->atapi_cap), DEBUG_PROBE); bzero(&saa, sizeof(saa)); saa.saa_sc_link = &as->sc_adapterlink; child = config_found((struct device *)as, &saa, scsiprint); if (child != NULL) { struct scsibus_softc *scsi = (struct scsibus_softc *)child; struct scsi_link *link = scsi_get_link(scsi, 0, 0); if (link) { strlcpy(drvp->drive_name, ((struct device *)(link->device_softc))->dv_xname, sizeof(drvp->drive_name)); wdc_print_caps(drvp); } } #ifdef WDCDEBUG if (chp->wdc->sc_dev.dv_cfdata->cf_flags & WDC_OPTION_PROBE_VERBOSE) wdcdebug_atapi_mask &= ~DEBUG_PROBE; #endif }
static void wdc_atapi_probe_device(struct atapibus_softc *sc, int target) { struct scsipi_channel *chan = sc->sc_channel; struct scsipi_periph *periph; struct ataparams ids; struct ataparams *id = &ids; struct wdc_softc *wdc = device_private(chan->chan_adapter->adapt_dev); struct atac_softc *atac = &wdc->sc_atac; struct ata_channel *chp = atac->atac_channels[chan->chan_channel]; struct ata_drive_datas *drvp = &chp->ch_drive[target]; struct scsipibus_attach_args sa; char serial_number[21], model[41], firmware_revision[9]; int s; /* skip if already attached */ if (scsipi_lookup_periph(chan, target, 0) != NULL) return; /* if no ATAPI device detected at wdc attach time, skip */ if (drvp->drive_type != ATA_DRIVET_ATAPI) { ATADEBUG_PRINT(("wdc_atapi_probe_device: " "drive %d not present\n", target), DEBUG_PROBE); return; } if (wdc_atapi_get_params(chan, target, id) == 0) { #ifdef ATAPI_DEBUG_PROBE printf("%s drive %d: cmdsz 0x%x drqtype 0x%x\n", device_xname(sc->sc_dev), target, id->atap_config & ATAPI_CFG_CMD_MASK, id->atap_config & ATAPI_CFG_DRQ_MASK); #endif periph = scsipi_alloc_periph(M_NOWAIT); if (periph == NULL) { aprint_error_dev(sc->sc_dev, "unable to allocate periph for drive %d\n", target); return; } periph->periph_dev = NULL; periph->periph_channel = chan; periph->periph_switch = &atapi_probe_periphsw; periph->periph_target = target; periph->periph_lun = 0; periph->periph_quirks = PQUIRK_ONLYBIG; #ifdef SCSIPI_DEBUG if (SCSIPI_DEBUG_TYPE == SCSIPI_BUSTYPE_ATAPI && SCSIPI_DEBUG_TARGET == target) periph->periph_dbflags |= SCSIPI_DEBUG_FLAGS; #endif periph->periph_type = ATAPI_CFG_TYPE(id->atap_config); if (id->atap_config & ATAPI_CFG_REMOV) periph->periph_flags |= PERIPH_REMOVABLE; if (periph->periph_type == T_SEQUENTIAL) { s = splbio(); drvp->drive_flags |= ATA_DRIVE_ATAPIDSCW; splx(s); } sa.sa_periph = periph; sa.sa_inqbuf.type = ATAPI_CFG_TYPE(id->atap_config); sa.sa_inqbuf.removable = id->atap_config & ATAPI_CFG_REMOV ? T_REMOV : T_FIXED; scsipi_strvis((u_char *)model, 40, id->atap_model, 40); scsipi_strvis((u_char *)serial_number, 20, id->atap_serial, 20); scsipi_strvis((u_char *)firmware_revision, 8, id->atap_revision, 8); sa.sa_inqbuf.vendor = model; sa.sa_inqbuf.product = serial_number; sa.sa_inqbuf.revision = firmware_revision; /* * Determine the operating mode capabilities of the device. */ if ((id->atap_config & ATAPI_CFG_CMD_MASK) == ATAPI_CFG_CMD_16) periph->periph_cap |= PERIPH_CAP_CMD16; /* XXX This is gross. */ periph->periph_cap |= (id->atap_config & ATAPI_CFG_DRQ_MASK); drvp->drv_softc = atapi_probe_device(sc, target, periph, &sa); if (drvp->drv_softc) ata_probe_caps(drvp); else { s = splbio(); drvp->drive_type = ATA_DRIVET_NONE; splx(s); } } else { s = splbio(); drvp->drive_type = ATA_DRIVET_NONE; splx(s); } }