Example #1
0
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
}
Example #2
0
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);
	}
}