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