int ioctl_ata(int min, int cmd, long arg) { struct ata_device *device = get_ata_device(min); struct ata_controller *cont = device->controller; if(!(device->flags & F_EXIST)) return -ENOENT; if(cmd == -1) { ata_disk_sync(primary); ata_disk_sync(secondary); return 0; } if(cmd == 0) { if(arg) *(unsigned *)arg = device->length; return 512; } if(cmd == 1) { kprintf("[ata]: reload partition tables - not implemented\n"); return 0; } if(cmd == -7) { if(arg) *(unsigned int *)arg = 512; return device->length; } return -EINVAL; }
smart_device * smart_interface::get_smart_device(const char * name, const char * type) { clear_err(); // Call platform specific autodetection if no device type specified smart_device * dev; if (!type || !*type) { dev = autodetect_smart_device(name); if (!dev && !get_errno()) set_err(EINVAL, "Unable to detect device type"); return dev; } // First check for platform specific device types dev = get_custom_smart_device(name, type); if (dev || get_errno()) return dev; if (!strcmp(type, "ata")) dev = get_ata_device(name, type); else if (!strcmp(type, "scsi")) dev = get_scsi_device(name, type); else if ( ((!strncmp(type, "sat", 3) && (!type[3] || strchr(",+", type[3]))) || (!strncmp(type, "usb", 3)))) { // Split "sat...+base..." -> ("sat...", "base...") unsigned satlen = strcspn(type, "+"); std::string sattype(type, satlen); const char * basetype = (type[satlen] ? type+satlen+1 : ""); // Recurse to allocate base device, default is standard SCSI if (!*basetype) basetype = "scsi"; smart_device_auto_ptr basedev( get_smart_device(name, basetype) ); if (!basedev) { set_err(EINVAL, "Type '%s+...': %s", sattype.c_str(), get_errmsg()); return 0; } // Result must be SCSI if (!basedev->is_scsi()) { set_err(EINVAL, "Type '%s+...': Device type '%s' is not SCSI", sattype.c_str(), basetype); return 0; } // Attach SAT tunnel ata_device * satdev = get_sat_device(sattype.c_str(), basedev->to_scsi()); if (!satdev) return 0; basedev.release(); return satdev; } else { set_err(EINVAL, "Unknown device type '%s'", type); return 0; } if (!dev && !get_errno()) set_err(EINVAL, "Not a device of type '%s'", type); return dev; }
bool legacy_smart_interface::scan_smart_devices(smart_device_list & devlist, const char * type, const char * pattern /*= 0*/) { if (pattern) { set_err(EINVAL, "DEVICESCAN with pattern not implemented yet"); return false; } // Make namelists char * * atanames = 0; int numata = 0; if (!type || !strcmp(type, "ata")) { numata = ::make_device_names(&atanames, "ATA"); if (numata < 0) { set_err(ENOMEM); return false; } } char * * scsinames = 0; int numscsi = 0; if (!type || !strcmp(type, "scsi")) { numscsi = ::make_device_names(&scsinames, "SCSI"); if (numscsi < 0) { free_devnames(atanames, numata); set_err(ENOMEM); return false; } } // Add to devlist int i; if (!type) type=""; for (i = 0; i < numata; i++) { ata_device * atadev = get_ata_device(atanames[i], type); if (atadev) devlist.push_back(atadev); } free_devnames(atanames, numata); for (i = 0; i < numscsi; i++) { scsi_device * scsidev = get_scsi_device(scsinames[i], type); if (scsidev) devlist.push_back(scsidev); } free_devnames(scsinames, numscsi); return true; }
int ata_rw_multiple(int rw, int dev, uint64_t blk, char *buf, int count) { if(!count) return 0; struct ata_device *device = get_ata_device(dev); struct ata_controller *cont = device->controller; if(!cont->enabled || !(device->flags & F_ENABLED)) return 0; if(!(device->flags & F_EXIST)) return 0; if(blk+count > device->length) return 0; int ret; if(device->flags & F_DMA && cont->dma_use && ATA_DMA_ENABLE) ret = ata_dma_rw(cont, device, rw, blk, (unsigned char *)buf, count); else ret = ata_pio_rw(cont, device, rw, blk, (unsigned char *)buf, count); return ret; }