Esempio n. 1
0
static int
sata_channel_detach(device_t dev)
{
	struct sata_softc *sc;
	struct ata_channel *ch;
	int error;

	sc = device_get_softc(device_get_parent(dev));
	ch = device_get_softc(dev);

	if (!ch->attached)
		return (0);

	/* Turn off EDMA engine */
	sata_edma_ctrl(dev, 0);

	/* Mask chanel interrupts */
	SATA_OUTL(sc, SATA_EDMA_IEMR(ch->unit), 0);
	SATA_OUTL(sc, SATA_MIMR, SATA_INL(sc, SATA_MIMR) & ~(
	    SATA_MICR_DONE(ch->unit) | SATA_MICR_DMADONE(ch->unit) |
	    SATA_MICR_ERR(ch->unit)));

	error = ata_detach(dev);
	ata_dmafini(dev);

	ch->attached = 0;

	return (error);
}
Esempio n. 2
0
static int
ata_cbuschannel_detach(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);

    if (!ch->attached)
	return (0);
    ch->attached = 0;

    return ata_detach(dev);
}
Esempio n. 3
0
static int
ata_pcichannel_detach(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);
    int error;

    if ((error = ata_detach(dev)))
	return error;

    if (ch->dma)
	ch->dma->free(dev);

    /* XXX SOS free resources for io and ctlio ?? */

    return 0;
}
Esempio n. 4
0
static int
ata_pccard_detach(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);
    int i;

    ata_detach(dev);
    if (ch->r_io[ATA_CONTROL].res != ch->r_io[ATA_DATA].res)
	bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID,
			     ch->r_io[ATA_CONTROL].res);
    bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID,
			 ch->r_io[ATA_DATA].res);
    for (i = ATA_DATA; i < ATA_MAX_RES; i++)
	ch->r_io[i].res = NULL;
    return 0;
}
Esempio n. 5
0
static int
ata_zbbus_detach(device_t dev)
{
	int error;
	struct ata_channel *ch = device_get_softc(dev);

	if (!ch->attached)
		return (0);
	ch->attached = 0;

	error = ata_detach(dev);

	bus_release_resource(dev, SYS_RES_MEMORY, 0,
			     ch->r_io[ATA_IDX_ADDR].res);

	return (error);
}
Esempio n. 6
0
static int
ata_isa_detach(device_t dev)
{
    struct ata_channel *ch = device_get_softc(dev);
    int error;

    if (!ch->attached)
	return (0);
    ch->attached = 0;

    error = ata_detach(dev);

    bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID,
	ch->r_io[ATA_CONTROL].res);
    bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID,
	ch->r_io[ATA_IDX_ADDR].res);
    return (error);
}
Esempio n. 7
0
static int
ata_pcichannel_detach(device_t dev)
{
    struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev));
    struct ata_channel *ch = device_get_softc(dev);
    int error;

    if (!ch->attached)
	return (0);
    ch->attached = 0;

    if ((error = ata_detach(dev)))
	return error;

    if (ctlr->ch_detach)
	return (ctlr->ch_detach(dev));

    return (0);
}
Esempio n. 8
0
static int
ataioctl(dev_t dev, u_long cmd, caddr_t addr, int32_t flag, struct proc *p)
{
    struct ata_cmd *iocmd = (struct ata_cmd *)addr;
    struct ata_channel *ch;
    device_t device = devclass_get_device(ata_devclass, iocmd->channel);
    int error;

    if (cmd != IOCATA)
	return ENOTTY;
    
    if (iocmd->channel < -1 || iocmd->device < -1 || iocmd->device > SLAVE)
	return ENXIO;

    switch (iocmd->cmd) {
	case ATAATTACH:
	    /* should enable channel HW on controller that can SOS XXX */   
	    error = ata_probe(device);
	    if (!error)
		error = ata_attach(device);
	    return error;

	case ATADETACH:
	    error = ata_detach(device);
	    /* should disable channel HW on controller that can SOS XXX */   
	    return error;

	case ATAREINIT:
	    if (!device || !(ch = device_get_softc(device)))
		return ENXIO;
	    ATA_SLEEPLOCK_CH(ch, ATA_ACTIVE);
	    if ((error = ata_reinit(ch)))
		ATA_UNLOCK_CH(ch);
	    return error;

	case ATAGMODE:
	    if (!device || !(ch = device_get_softc(device)))
		return ENXIO;

	    if ((iocmd->device == MASTER || iocmd->device == -1) &&
		ch->device[MASTER].driver)
		iocmd->u.mode.mode[MASTER] = ch->device[MASTER].mode;
	    else
		iocmd->u.mode.mode[MASTER] = -1;

	    if ((iocmd->device == SLAVE || iocmd->device == -1) &&
		ch->device[SLAVE].param)
		iocmd->u.mode.mode[SLAVE] = ch->device[SLAVE].mode;
	    else
		iocmd->u.mode.mode[SLAVE] = -1;
	    return 0;

	case ATASMODE:
	    if (!device || !(ch = device_get_softc(device)))
		return ENXIO;

	    if ((iocmd->device == MASTER || iocmd->device == -1) &&
		iocmd->u.mode.mode[MASTER] >= 0 && ch->device[MASTER].param) {
		ata_change_mode(&ch->device[MASTER],iocmd->u.mode.mode[MASTER]);
		iocmd->u.mode.mode[MASTER] = ch->device[MASTER].mode;
	    }
	    else
		iocmd->u.mode.mode[MASTER] = -1;

	    if ((iocmd->device == SLAVE || iocmd->device == -1) &&
		iocmd->u.mode.mode[SLAVE] >= 0 && ch->device[SLAVE].param) {
		ata_change_mode(&ch->device[SLAVE], iocmd->u.mode.mode[SLAVE]);
		iocmd->u.mode.mode[SLAVE] = ch->device[SLAVE].mode;
	    }
	    else
		iocmd->u.mode.mode[SLAVE] = -1;
	    return 0;

	case ATAGPARM:
	    if (!device || !(ch = device_get_softc(device)))
		return ENXIO;

	    iocmd->u.param.type[MASTER] = 
		ch->devices & (ATA_ATA_MASTER | ATA_ATAPI_MASTER);
	    iocmd->u.param.type[SLAVE] =
		ch->devices & (ATA_ATA_SLAVE | ATA_ATAPI_SLAVE);

	    if (ch->device[MASTER].name)
		strcpy(iocmd->u.param.name[MASTER], ch->device[MASTER].name);
	    if (ch->device[SLAVE].name)
		strcpy(iocmd->u.param.name[SLAVE], ch->device[SLAVE].name);

	    if (ch->device[MASTER].param)
		bcopy(ch->device[MASTER].param, &iocmd->u.param.params[MASTER],
		      sizeof(struct ata_params));
	    if (ch->device[SLAVE].param)
		bcopy(ch->device[SLAVE].param, &iocmd->u.param.params[SLAVE],
		      sizeof(struct ata_params));
	    return 0;

	case ATAENCSTAT: {
	    struct ata_device *atadev;

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

	    if (iocmd->device == SLAVE)
		atadev = &ch->device[SLAVE];
	    else
		atadev = &ch->device[MASTER];

	    return ata_enclosure_status(atadev,
					&iocmd->u.enclosure.fan,
					&iocmd->u.enclosure.temp,
					&iocmd->u.enclosure.v05,
					&iocmd->u.enclosure.v12);
	}

#if NATADISK > 0
	case ATARAIDREBUILD:
	    return ata_raid_rebuild(iocmd->channel);

	case ATARAIDCREATE:
	    return ata_raid_create(&iocmd->u.raid_setup);

	case ATARAIDDELETE:
	    return ata_raid_delete(iocmd->channel);

	case ATARAIDSTATUS:
	    return ata_raid_status(iocmd->channel, &iocmd->u.raid_status);
#endif
#if DEV_ATAPIALL
	case ATAPICMD: {
	    struct ata_device *atadev;
	    caddr_t buf;

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

	    if (!(atadev = &ch->device[iocmd->device]) ||
		!(ch->devices & (iocmd->device == MASTER ?
				 ATA_ATAPI_MASTER : ATA_ATAPI_SLAVE)))
		return ENODEV;

	    if (!(buf = malloc(iocmd->u.atapi.count, M_ATA, M_NOWAIT)))
		return ENOMEM;

	    if (iocmd->u.atapi.flags & ATAPI_CMD_WRITE) {
		error = copyin(iocmd->u.atapi.data, buf, iocmd->u.atapi.count);
		if (error)
		    return error;
	    }
	    error = atapi_queue_cmd(atadev, iocmd->u.atapi.ccb,
				    buf, iocmd->u.atapi.count,
				    (iocmd->u.atapi.flags == ATAPI_CMD_READ ?
				     ATPR_F_READ : 0) | ATPR_F_QUIET, 
				    iocmd->u.atapi.timeout, NULL, NULL);
	    if (error) {
		iocmd->u.atapi.error = error;
		bcopy(&atadev->result, iocmd->u.atapi.sense_data,
		      sizeof(struct atapi_reqsense));
		error = 0;
	    }
	    else if (iocmd->u.atapi.flags & ATAPI_CMD_READ)
		error = copyout(buf, iocmd->u.atapi.data, iocmd->u.atapi.count);

	    free(buf, M_ATA);
	    return error;
	}
#endif
	default:
	    break;
    }
    return ENOTTY;
}
/*
 * device related interfaces
 */
static int
ata_ioctl(struct cdev *dev, u_long cmd, caddr_t data,
	  int32_t flag, struct thread *td)
{
    device_t device, *children;
    struct ata_ioc_devices *devices = (struct ata_ioc_devices *)data;
    int *value = (int *)data;
    int i, nchildren, error = ENOTTY;

    switch (cmd) {
    case IOCATAGMAXCHANNEL:
	/* In case we have channel 0..n this will return n+1. */
	*value = devclass_get_maxunit(ata_devclass);
	error = 0;
	break;

    case IOCATAREINIT:
	if (*value >= devclass_get_maxunit(ata_devclass) ||
	    !(device = devclass_get_device(ata_devclass, *value)))
	    return ENXIO;
	error = ata_reinit(device);
	break;

    case IOCATAATTACH:
	if (*value >= devclass_get_maxunit(ata_devclass) ||
	    !(device = devclass_get_device(ata_devclass, *value)))
	    return ENXIO;
	/* XXX SOS should enable channel HW on controller */
	error = ata_attach(device);
	break;

    case IOCATADETACH:
	if (*value >= devclass_get_maxunit(ata_devclass) ||
	    !(device = devclass_get_device(ata_devclass, *value)))
	    return ENXIO;
	error = ata_detach(device);
	/* XXX SOS should disable channel HW on controller */
	break;

    case IOCATADEVICES:
	if (devices->channel >= devclass_get_maxunit(ata_devclass) ||
	    !(device = devclass_get_device(ata_devclass, devices->channel)))
	    return ENXIO;
	bzero(devices->name[0], 32);
	bzero(&devices->params[0], sizeof(struct ata_params));
	bzero(devices->name[1], 32);
	bzero(&devices->params[1], sizeof(struct ata_params));
	if (!device_get_children(device, &children, &nchildren)) {
	    for (i = 0; i < nchildren; i++) {
		if (children[i] && device_is_attached(children[i])) {
		    struct ata_device *atadev = device_get_softc(children[i]);

		    if (atadev->unit == ATA_MASTER) {
			strncpy(devices->name[0],
				device_get_nameunit(children[i]), 32);
			bcopy(&atadev->param, &devices->params[0],
			      sizeof(struct ata_params));
		    }
		    if (atadev->unit == ATA_SLAVE) {
			strncpy(devices->name[1],
				device_get_nameunit(children[i]), 32);
			bcopy(&atadev->param, &devices->params[1],
			      sizeof(struct ata_params));
		    }
		}
	    }
	    free(children, M_TEMP);
	    error = 0;
	}
	else
	    error = ENODEV;
	break;

    default:
	if (ata_raid_ioctl_func)
	    error = ata_raid_ioctl_func(cmd, data);
    }
    return error;
}