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); }
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); }
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; }
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; }
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); }
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); }
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); }
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; }