int
ata_identify(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);
    struct ata_device *master = NULL, *slave = NULL;
    device_t master_child = NULL, slave_child = NULL;
    int master_unit = -1, slave_unit = -1;

    if (ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER)) {
	if (!(master = malloc(sizeof(struct ata_device),
			      M_ATA, M_NOWAIT | M_ZERO))) {
	    device_printf(dev, "out of memory\n");
	    return ENOMEM;
	}
	master->unit = ATA_MASTER;
    }
    if (ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE)) {
	if (!(slave = malloc(sizeof(struct ata_device),
			     M_ATA, M_NOWAIT | M_ZERO))) {
	    free(master, M_ATA);
	    device_printf(dev, "out of memory\n");
	    return ENOMEM;
	}
	slave->unit = ATA_SLAVE;
    }

#ifdef ATA_STATIC_ID
    if (ch->devices & ATA_ATA_MASTER)
	master_unit = (device_get_unit(dev) << 1);
#endif
    if (master && !(master_child = ata_add_child(dev, master, master_unit))) {
	free(master, M_ATA);
	master = NULL;
    }
#ifdef ATA_STATIC_ID
    if (ch->devices & ATA_ATA_SLAVE)
	slave_unit = (device_get_unit(dev) << 1) + 1;
#endif
    if (slave && !(slave_child = ata_add_child(dev, slave, slave_unit))) {
	free(slave, M_ATA);
	slave = NULL;
    }

    if (slave && ata_getparam(slave, 1)) {
	device_delete_child(dev, slave_child);
	free(slave, M_ATA);
    }
    if (master && ata_getparam(master, 1)) {
	device_delete_child(dev, master_child);
	free(master, M_ATA);
    }

    bus_generic_probe(dev);
    bus_generic_attach(dev);
    return 0;
}
Esempio n. 2
0
int
ata_reinit(struct ata_channel *ch)
{
    int devices, misdev, newdev;

    if (!ch->r_io || !ch->r_altio || !ch->r_irq)
	return ENXIO;

    ATA_FORCELOCK_CH(ch, ATA_CONTROL);
    ch->running = NULL;
    devices = ch->devices;
    ata_printf(ch, -1, "resetting devices .. ");
    ata_reset(ch);

    if ((misdev = devices & ~ch->devices)) {
	if (misdev)
	    printf("\n");
#if NATADISK > 0
	if (misdev & ATA_ATA_MASTER && ch->device[MASTER].driver)
	    ad_detach(&ch->device[MASTER], 0);
	if (misdev & ATA_ATA_SLAVE && ch->device[SLAVE].driver)
	    ad_detach(&ch->device[SLAVE], 0);
#endif
#if DEV_ATAPIALL
	if (misdev & ATA_ATAPI_MASTER && ch->device[MASTER].driver)
	    atapi_detach(&ch->device[MASTER]);
	if (misdev & ATA_ATAPI_SLAVE && ch->device[SLAVE].driver)
	    atapi_detach(&ch->device[SLAVE]);
#endif
	if (misdev & ATA_ATA_MASTER || misdev & ATA_ATAPI_MASTER) {
	    if (ch->device[MASTER].param)
		free(ch->device[MASTER].param, M_ATA);
	    ch->device[MASTER].param = NULL;
	}
	if (misdev & ATA_ATA_SLAVE || misdev & ATA_ATAPI_SLAVE) {
	    if (ch->device[SLAVE].param)
		free(ch->device[SLAVE].param, M_ATA);
	    ch->device[SLAVE].param = NULL;
	}
    }
    if ((newdev = ~devices & ch->devices)) {
	if (newdev & ATA_ATA_MASTER)
	    if (ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY))
		ch->devices &= ~ATA_ATA_MASTER;
	if (newdev & ATA_ATA_SLAVE)
	    if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY))
		ch->devices &= ~ATA_ATA_SLAVE;
	if (newdev & ATA_ATAPI_MASTER)
	    if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY))
		ch->devices &= ~ATA_ATAPI_MASTER;
	if (newdev & ATA_ATAPI_SLAVE)
	    if (ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY))
		ch->devices &= ~ATA_ATAPI_SLAVE;
    }
    newdev = ~devices & ch->devices;
    if (!misdev && newdev)
	printf("\n");
#if NATADISK > 0
    if (newdev & ATA_ATA_MASTER && !ch->device[MASTER].driver)
	ad_attach(&ch->device[MASTER], 1);
    else if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) {
	ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY);
	ad_reinit(&ch->device[MASTER]);
    }
    if (newdev & ATA_ATA_SLAVE && !ch->device[SLAVE].driver)
	ad_attach(&ch->device[SLAVE], 1);
    else if (ch->devices & (ATA_ATA_SLAVE) && ch->device[SLAVE].driver) {
	ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY);
	ad_reinit(&ch->device[SLAVE]);
    }
#endif
#if DEV_ATAPIALL
    if (newdev & ATA_ATAPI_MASTER && !ch->device[MASTER].driver)
	atapi_attach(&ch->device[MASTER], 1);
    else if (ch->devices & (ATA_ATAPI_MASTER) && ch->device[MASTER].driver) {
	ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY);
	atapi_reinit(&ch->device[MASTER]);
    }
    if (newdev & ATA_ATAPI_SLAVE && !ch->device[SLAVE].driver)
	atapi_attach(&ch->device[SLAVE], 1);
    else if (ch->devices & (ATA_ATAPI_SLAVE) && ch->device[SLAVE].driver) {
	ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY);
	atapi_reinit(&ch->device[SLAVE]);
    }
#endif
#if NATAPICAM > 0
    if (ch->devices & (ATA_ATAPI_MASTER | ATA_ATAPI_SLAVE))
	atapi_cam_reinit_bus(ch);
#endif
    printf("done\n");
    ATA_UNLOCK_CH(ch);
    ata_start(ch);
    return 0;
}
Esempio n. 3
0
static void 
ata_boot_attach(void)
{
    struct ata_channel *ch;
    int ctlr, s;

    if (ata_delayed_attach) {
	config_intrhook_disestablish(ata_delayed_attach);
	free(ata_delayed_attach, M_TEMP);
	ata_delayed_attach = NULL;
    }
    s = splbio();

    /*
     * run through all ata devices and look for real ATA & ATAPI devices
     * using the hints we found in the early probe, this avoids some of
     * the delays probing of non-exsistent devices can cause.
     */
    for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
	if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
	    continue;
	if (ch->devices & ATA_ATA_SLAVE)
	    if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY))
		ch->devices &= ~ATA_ATA_SLAVE;
	if (ch->devices & ATA_ATAPI_SLAVE)
	    if (ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY))
		ch->devices &= ~ATA_ATAPI_SLAVE;
	if (ch->devices & ATA_ATA_MASTER)
	    if (ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY))
		ch->devices &= ~ATA_ATA_MASTER;
	if (ch->devices & ATA_ATAPI_MASTER)
	    if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY))
		ch->devices &= ~ATA_ATAPI_MASTER;
    }

#if NATADISK > 0
    /* now we know whats there, do the real attach, first the ATA disks */
    for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
	if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
	    continue;
	if (ch->devices & ATA_ATA_MASTER)
	    ad_attach(&ch->device[MASTER], 0);
	if (ch->devices & ATA_ATA_SLAVE)
	    ad_attach(&ch->device[SLAVE], 0);
    }
    ata_raid_attach();
#endif
#if DEV_ATAPIALL
    /* then the atapi devices */
    for (ctlr=0; ctlr<devclass_get_maxunit(ata_devclass); ctlr++) {
	if (!(ch = devclass_get_softc(ata_devclass, ctlr)))
	    continue;
	if (ch->devices & ATA_ATAPI_MASTER)
	    atapi_attach(&ch->device[MASTER], 0);
	if (ch->devices & ATA_ATAPI_SLAVE)
	    atapi_attach(&ch->device[SLAVE], 0);
#if NATAPICAM > 0
	atapi_cam_attach_bus(ch);
#endif
    }
#endif
    splx(s);
}
Esempio n. 4
0
int
ata_attach(device_t dev)
{
    struct ata_channel *ch;
    int error, rid;

    if (!dev || !(ch = device_get_softc(dev)))
	return ENXIO;

    rid = ATA_IRQ_RID;
    ch->r_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
				   RF_SHAREABLE | RF_ACTIVE);
    if (!ch->r_irq) {
	ata_printf(ch, -1, "unable to allocate interrupt\n");
	return ENXIO;
    }
    if ((error = bus_setup_intr(dev, ch->r_irq, INTR_TYPE_BIO,
				ata_intr, ch, &ch->ih))) {
	ata_printf(ch, -1, "unable to setup interrupt\n");
	return error;
    }

    /*
     * do not attach devices if we are in early boot, this is done later 
     * when interrupts are enabled by a hook into the boot process.
     * otherwise attach what the probe has found in ch->devices.
     */
    if (!ata_delayed_attach) {
	int s = splbio();

	if (ch->devices & ATA_ATA_SLAVE)
	    if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY))
		ch->devices &= ~ATA_ATA_SLAVE;
	if (ch->devices & ATA_ATAPI_SLAVE)
	    if (ata_getparam(&ch->device[SLAVE], ATA_C_ATAPI_IDENTIFY))
		ch->devices &= ~ATA_ATAPI_SLAVE;
	if (ch->devices & ATA_ATA_MASTER)
	    if (ata_getparam(&ch->device[MASTER], ATA_C_ATA_IDENTIFY))
		ch->devices &= ~ATA_ATA_MASTER;
	if (ch->devices & ATA_ATAPI_MASTER)
	    if (ata_getparam(&ch->device[MASTER], ATA_C_ATAPI_IDENTIFY))
		ch->devices &= ~ATA_ATAPI_MASTER;
#if NATADISK > 0
	if (ch->devices & ATA_ATA_MASTER)
	    ad_attach(&ch->device[MASTER], 0);
	if (ch->devices & ATA_ATA_SLAVE)
	    ad_attach(&ch->device[SLAVE], 0);
#endif
#if DEV_ATAPIALL
	if (ch->devices & ATA_ATAPI_MASTER)
	    atapi_attach(&ch->device[MASTER], 0);
	if (ch->devices & ATA_ATAPI_SLAVE)
	    atapi_attach(&ch->device[SLAVE], 0);
#endif
#if NATAPICAM > 0
	atapi_cam_attach_bus(ch);
#endif
	splx(s);
    }
    return 0;
}
int
ata_device_ioctl(device_t dev, u_long cmd, caddr_t data)
{
    struct ata_device *atadev = device_get_softc(dev);
    struct ata_channel *ch = device_get_softc(device_get_parent(dev));
    struct ata_ioc_request *ioc_request = (struct ata_ioc_request *)data;
    struct ata_params *params = (struct ata_params *)data;
    int *mode = (int *)data;
    struct ata_request *request;
    caddr_t buf;
    int error;

    switch (cmd) {
    case IOCATAREQUEST:
	if (ioc_request->count >
	    (ch->dma->max_iosize ? ch->dma->max_iosize : DFLTPHYS)) {
		return (EFBIG);
	}
	if (!(buf = malloc(ioc_request->count, M_ATA, M_NOWAIT))) {
	    return ENOMEM;
	}
	if (!(request = ata_alloc_request())) {
	    free(buf, M_ATA);
	    return  ENOMEM;
	}
	if (ioc_request->flags & ATA_CMD_WRITE) {
	    error = copyin(ioc_request->data, buf, ioc_request->count);
	    if (error) {
		free(buf, M_ATA);
		ata_free_request(request);
		return error;
	    }
	}
	request->dev = dev;
	if (ioc_request->flags & ATA_CMD_ATAPI) {
	    request->flags = ATA_R_ATAPI;
	    bcopy(ioc_request->u.atapi.ccb, request->u.atapi.ccb, 16);
	}
	else {
	    request->u.ata.command = ioc_request->u.ata.command;
	    request->u.ata.feature = ioc_request->u.ata.feature;
	    request->u.ata.lba = ioc_request->u.ata.lba;
	    request->u.ata.count = ioc_request->u.ata.count;
	}
	request->timeout = ioc_request->timeout;
	request->data = buf;
	request->bytecount = ioc_request->count;
	request->transfersize = request->bytecount;
	if (ioc_request->flags & ATA_CMD_CONTROL)
	    request->flags |= ATA_R_CONTROL;
	if (ioc_request->flags & ATA_CMD_READ)
	    request->flags |= ATA_R_READ;
	if (ioc_request->flags & ATA_CMD_WRITE)
	    request->flags |= ATA_R_WRITE;
	ata_queue_request(request);
	if (request->flags & ATA_R_ATAPI) {
	    bcopy(&request->u.atapi.sense, &ioc_request->u.atapi.sense,
		  sizeof(struct atapi_sense));
	}
	else {
	    ioc_request->u.ata.command = request->u.ata.command;
	    ioc_request->u.ata.feature = request->u.ata.feature;
	    ioc_request->u.ata.lba = request->u.ata.lba;
	    ioc_request->u.ata.count = request->u.ata.count;
	}
	ioc_request->error = request->result;
	if (ioc_request->flags & ATA_CMD_READ)
	    error = copyout(buf, ioc_request->data, ioc_request->count);
	else
	    error = 0;
	free(buf, M_ATA);
	ata_free_request(request);
	return error;
   
    case IOCATAGPARM:
	ata_getparam(atadev, 0);
	bcopy(&atadev->param, params, sizeof(struct ata_params));
	return 0;
	
    case IOCATASMODE:
	atadev->mode = *mode;
	ATA_SETMODE(device_get_parent(dev), dev);
	return 0;

    case IOCATAGMODE:
	*mode = atadev->mode;
	return 0;
    case IOCATASSPINDOWN:
	atadev->spindown = *mode;
	return 0;
    case IOCATAGSPINDOWN:
	*mode = atadev->spindown;
	return 0;
    default:
	return ENOTTY;
    }
}