|
@@ -168,12 +168,11 @@ static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR,
|
|
|
|
|
|
static int idebus_parameter; /* holds the "idebus=" parameter */
|
|
|
static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */
|
|
|
-static int initializing; /* set while initializing built-in drivers */
|
|
|
|
|
|
DECLARE_MUTEX(ide_cfg_sem);
|
|
|
__cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock);
|
|
|
|
|
|
-#ifdef CONFIG_BLK_DEV_IDEPCI
|
|
|
+#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
|
|
|
static int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */
|
|
|
#endif
|
|
|
|
|
@@ -216,9 +215,6 @@ static void init_hwif_data(ide_hwif_t *hwif, unsigned int index)
|
|
|
hwif->bus_state = BUSSTATE_ON;
|
|
|
|
|
|
hwif->atapi_dma = 0; /* disable all atapi dma */
|
|
|
- hwif->ultra_mask = 0x80; /* disable all ultra */
|
|
|
- hwif->mwdma_mask = 0x80; /* disable all mwdma */
|
|
|
- hwif->swdma_mask = 0x80; /* disable all swdma */
|
|
|
|
|
|
init_completion(&hwif->gendev_rel_comp);
|
|
|
|
|
@@ -305,9 +301,7 @@ static void __init init_ide_data (void)
|
|
|
#endif
|
|
|
}
|
|
|
#ifdef CONFIG_IDE_ARM
|
|
|
- initializing = 1;
|
|
|
ide_arm_init();
|
|
|
- initializing = 0;
|
|
|
#endif
|
|
|
}
|
|
|
|
|
@@ -353,10 +347,6 @@ static int ide_system_bus_speed(void)
|
|
|
return system_bus_speed;
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_PROC_FS
|
|
|
-struct proc_dir_entry *proc_ide_root;
|
|
|
-#endif
|
|
|
-
|
|
|
static struct resource* hwif_request_region(ide_hwif_t *hwif,
|
|
|
unsigned long addr, int num)
|
|
|
{
|
|
@@ -480,6 +470,7 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
|
|
|
|
|
|
hwif->tuneproc = tmp_hwif->tuneproc;
|
|
|
hwif->speedproc = tmp_hwif->speedproc;
|
|
|
+ hwif->udma_filter = tmp_hwif->udma_filter;
|
|
|
hwif->selectproc = tmp_hwif->selectproc;
|
|
|
hwif->reset_poll = tmp_hwif->reset_poll;
|
|
|
hwif->pre_reset = tmp_hwif->pre_reset;
|
|
@@ -599,7 +590,7 @@ void ide_unregister(unsigned int index)
|
|
|
|
|
|
spin_unlock_irq(&ide_lock);
|
|
|
|
|
|
- destroy_proc_ide_interface(hwif);
|
|
|
+ ide_proc_unregister_port(hwif);
|
|
|
|
|
|
hwgroup = hwif->hwgroup;
|
|
|
/*
|
|
@@ -751,6 +742,7 @@ void ide_setup_ports ( hw_regs_t *hw,
|
|
|
/**
|
|
|
* ide_register_hw_with_fixup - register IDE interface
|
|
|
* @hw: hardware registers
|
|
|
+ * @initializing: set while initializing built-in drivers
|
|
|
* @hwifp: pointer to returned hwif
|
|
|
* @fixup: fixup function
|
|
|
*
|
|
@@ -760,7 +752,9 @@ void ide_setup_ports ( hw_regs_t *hw,
|
|
|
* Returns -1 on error.
|
|
|
*/
|
|
|
|
|
|
-int ide_register_hw_with_fixup(hw_regs_t *hw, ide_hwif_t **hwifp, void(*fixup)(ide_hwif_t *hwif))
|
|
|
+int ide_register_hw_with_fixup(hw_regs_t *hw, int initializing,
|
|
|
+ ide_hwif_t **hwifp,
|
|
|
+ void(*fixup)(ide_hwif_t *hwif))
|
|
|
{
|
|
|
int index, retry = 1;
|
|
|
ide_hwif_t *hwif;
|
|
@@ -801,7 +795,7 @@ found:
|
|
|
|
|
|
if (!initializing) {
|
|
|
probe_hwif_init_with_fixup(hwif, fixup);
|
|
|
- create_proc_ide_interfaces();
|
|
|
+ ide_proc_register_port(hwif);
|
|
|
}
|
|
|
|
|
|
if (hwifp)
|
|
@@ -812,9 +806,9 @@ found:
|
|
|
|
|
|
EXPORT_SYMBOL(ide_register_hw_with_fixup);
|
|
|
|
|
|
-int ide_register_hw(hw_regs_t *hw, ide_hwif_t **hwifp)
|
|
|
+int ide_register_hw(hw_regs_t *hw, int initializing, ide_hwif_t **hwifp)
|
|
|
{
|
|
|
- return ide_register_hw_with_fixup(hw, hwifp, NULL);
|
|
|
+ return ide_register_hw_with_fixup(hw, initializing, hwifp, NULL);
|
|
|
}
|
|
|
|
|
|
EXPORT_SYMBOL(ide_register_hw);
|
|
@@ -825,205 +819,7 @@ EXPORT_SYMBOL(ide_register_hw);
|
|
|
|
|
|
DECLARE_MUTEX(ide_setting_sem);
|
|
|
|
|
|
-/**
|
|
|
- * __ide_add_setting - add an ide setting option
|
|
|
- * @drive: drive to use
|
|
|
- * @name: setting name
|
|
|
- * @rw: true if the function is read write
|
|
|
- * @read_ioctl: function to call on read
|
|
|
- * @write_ioctl: function to call on write
|
|
|
- * @data_type: type of data
|
|
|
- * @min: range minimum
|
|
|
- * @max: range maximum
|
|
|
- * @mul_factor: multiplication scale
|
|
|
- * @div_factor: divison scale
|
|
|
- * @data: private data field
|
|
|
- * @set: setting
|
|
|
- * @auto_remove: setting auto removal flag
|
|
|
- *
|
|
|
- * Removes the setting named from the device if it is present.
|
|
|
- * The function takes the settings_lock to protect against
|
|
|
- * parallel changes. This function must not be called from IRQ
|
|
|
- * context. Returns 0 on success or -1 on failure.
|
|
|
- *
|
|
|
- * BUGS: This code is seriously over-engineered. There is also
|
|
|
- * magic about how the driver specific features are setup. If
|
|
|
- * a driver is attached we assume the driver settings are auto
|
|
|
- * remove.
|
|
|
- */
|
|
|
-
|
|
|
-static int __ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set, int auto_remove)
|
|
|
-{
|
|
|
- ide_settings_t **p = (ide_settings_t **) &drive->settings, *setting = NULL;
|
|
|
-
|
|
|
- down(&ide_setting_sem);
|
|
|
- while ((*p) && strcmp((*p)->name, name) < 0)
|
|
|
- p = &((*p)->next);
|
|
|
- if ((setting = kzalloc(sizeof(*setting), GFP_KERNEL)) == NULL)
|
|
|
- goto abort;
|
|
|
- if ((setting->name = kmalloc(strlen(name) + 1, GFP_KERNEL)) == NULL)
|
|
|
- goto abort;
|
|
|
- strcpy(setting->name, name);
|
|
|
- setting->rw = rw;
|
|
|
- setting->read_ioctl = read_ioctl;
|
|
|
- setting->write_ioctl = write_ioctl;
|
|
|
- setting->data_type = data_type;
|
|
|
- setting->min = min;
|
|
|
- setting->max = max;
|
|
|
- setting->mul_factor = mul_factor;
|
|
|
- setting->div_factor = div_factor;
|
|
|
- setting->data = data;
|
|
|
- setting->set = set;
|
|
|
-
|
|
|
- setting->next = *p;
|
|
|
- if (auto_remove)
|
|
|
- setting->auto_remove = 1;
|
|
|
- *p = setting;
|
|
|
- up(&ide_setting_sem);
|
|
|
- return 0;
|
|
|
-abort:
|
|
|
- up(&ide_setting_sem);
|
|
|
- kfree(setting);
|
|
|
- return -1;
|
|
|
-}
|
|
|
-
|
|
|
-int ide_add_setting(ide_drive_t *drive, const char *name, int rw, int read_ioctl, int write_ioctl, int data_type, int min, int max, int mul_factor, int div_factor, void *data, ide_procset_t *set)
|
|
|
-{
|
|
|
- return __ide_add_setting(drive, name, rw, read_ioctl, write_ioctl, data_type, min, max, mul_factor, div_factor, data, set, 1);
|
|
|
-}
|
|
|
-
|
|
|
-EXPORT_SYMBOL(ide_add_setting);
|
|
|
-
|
|
|
-/**
|
|
|
- * __ide_remove_setting - remove an ide setting option
|
|
|
- * @drive: drive to use
|
|
|
- * @name: setting name
|
|
|
- *
|
|
|
- * Removes the setting named from the device if it is present.
|
|
|
- * The caller must hold the setting semaphore.
|
|
|
- */
|
|
|
-
|
|
|
-static void __ide_remove_setting (ide_drive_t *drive, char *name)
|
|
|
-{
|
|
|
- ide_settings_t **p, *setting;
|
|
|
-
|
|
|
- p = (ide_settings_t **) &drive->settings;
|
|
|
-
|
|
|
- while ((*p) && strcmp((*p)->name, name))
|
|
|
- p = &((*p)->next);
|
|
|
- if ((setting = (*p)) == NULL)
|
|
|
- return;
|
|
|
-
|
|
|
- (*p) = setting->next;
|
|
|
-
|
|
|
- kfree(setting->name);
|
|
|
- kfree(setting);
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * ide_find_setting_by_ioctl - find a drive specific ioctl
|
|
|
- * @drive: drive to scan
|
|
|
- * @cmd: ioctl command to handle
|
|
|
- *
|
|
|
- * Scan's the device setting table for a matching entry and returns
|
|
|
- * this or NULL if no entry is found. The caller must hold the
|
|
|
- * setting semaphore
|
|
|
- */
|
|
|
-
|
|
|
-static ide_settings_t *ide_find_setting_by_ioctl (ide_drive_t *drive, int cmd)
|
|
|
-{
|
|
|
- ide_settings_t *setting = drive->settings;
|
|
|
-
|
|
|
- while (setting) {
|
|
|
- if (setting->read_ioctl == cmd || setting->write_ioctl == cmd)
|
|
|
- break;
|
|
|
- setting = setting->next;
|
|
|
- }
|
|
|
-
|
|
|
- return setting;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * ide_find_setting_by_name - find a drive specific setting
|
|
|
- * @drive: drive to scan
|
|
|
- * @name: setting name
|
|
|
- *
|
|
|
- * Scan's the device setting table for a matching entry and returns
|
|
|
- * this or NULL if no entry is found. The caller must hold the
|
|
|
- * setting semaphore
|
|
|
- */
|
|
|
-
|
|
|
-ide_settings_t *ide_find_setting_by_name (ide_drive_t *drive, char *name)
|
|
|
-{
|
|
|
- ide_settings_t *setting = drive->settings;
|
|
|
-
|
|
|
- while (setting) {
|
|
|
- if (strcmp(setting->name, name) == 0)
|
|
|
- break;
|
|
|
- setting = setting->next;
|
|
|
- }
|
|
|
- return setting;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * auto_remove_settings - remove driver specific settings
|
|
|
- * @drive: drive
|
|
|
- *
|
|
|
- * Automatically remove all the driver specific settings for this
|
|
|
- * drive. This function may not be called from IRQ context. The
|
|
|
- * caller must hold ide_setting_sem.
|
|
|
- */
|
|
|
-
|
|
|
-static void auto_remove_settings (ide_drive_t *drive)
|
|
|
-{
|
|
|
- ide_settings_t *setting;
|
|
|
-repeat:
|
|
|
- setting = drive->settings;
|
|
|
- while (setting) {
|
|
|
- if (setting->auto_remove) {
|
|
|
- __ide_remove_setting(drive, setting->name);
|
|
|
- goto repeat;
|
|
|
- }
|
|
|
- setting = setting->next;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * ide_read_setting - read an IDE setting
|
|
|
- * @drive: drive to read from
|
|
|
- * @setting: drive setting
|
|
|
- *
|
|
|
- * Read a drive setting and return the value. The caller
|
|
|
- * must hold the ide_setting_sem when making this call.
|
|
|
- *
|
|
|
- * BUGS: the data return and error are the same return value
|
|
|
- * so an error -EINVAL and true return of the same value cannot
|
|
|
- * be told apart
|
|
|
- */
|
|
|
-
|
|
|
-int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting)
|
|
|
-{
|
|
|
- int val = -EINVAL;
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
- if ((setting->rw & SETTING_READ)) {
|
|
|
- spin_lock_irqsave(&ide_lock, flags);
|
|
|
- switch(setting->data_type) {
|
|
|
- case TYPE_BYTE:
|
|
|
- val = *((u8 *) setting->data);
|
|
|
- break;
|
|
|
- case TYPE_SHORT:
|
|
|
- val = *((u16 *) setting->data);
|
|
|
- break;
|
|
|
- case TYPE_INT:
|
|
|
- case TYPE_INTA:
|
|
|
- val = *((u32 *) setting->data);
|
|
|
- break;
|
|
|
- }
|
|
|
- spin_unlock_irqrestore(&ide_lock, flags);
|
|
|
- }
|
|
|
- return val;
|
|
|
-}
|
|
|
+EXPORT_SYMBOL_GPL(ide_setting_sem);
|
|
|
|
|
|
/**
|
|
|
* ide_spin_wait_hwgroup - wait for group
|
|
@@ -1058,61 +854,14 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive)
|
|
|
|
|
|
EXPORT_SYMBOL(ide_spin_wait_hwgroup);
|
|
|
|
|
|
-/**
|
|
|
- * ide_write_setting - read an IDE setting
|
|
|
- * @drive: drive to read from
|
|
|
- * @setting: drive setting
|
|
|
- * @val: value
|
|
|
- *
|
|
|
- * Write a drive setting if it is possible. The caller
|
|
|
- * must hold the ide_setting_sem when making this call.
|
|
|
- *
|
|
|
- * BUGS: the data return and error are the same return value
|
|
|
- * so an error -EINVAL and true return of the same value cannot
|
|
|
- * be told apart
|
|
|
- *
|
|
|
- * FIXME: This should be changed to enqueue a special request
|
|
|
- * to the driver to change settings, and then wait on a sema for completion.
|
|
|
- * The current scheme of polling is kludgy, though safe enough.
|
|
|
- */
|
|
|
-
|
|
|
-int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
|
|
|
+int set_io_32bit(ide_drive_t *drive, int arg)
|
|
|
{
|
|
|
- int i;
|
|
|
- u32 *p;
|
|
|
-
|
|
|
- if (!capable(CAP_SYS_ADMIN))
|
|
|
- return -EACCES;
|
|
|
- if (!(setting->rw & SETTING_WRITE))
|
|
|
+ if (drive->no_io_32bit)
|
|
|
return -EPERM;
|
|
|
- if (val < setting->min || val > setting->max)
|
|
|
+
|
|
|
+ if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1))
|
|
|
return -EINVAL;
|
|
|
- if (setting->set)
|
|
|
- return setting->set(drive, val);
|
|
|
- if (ide_spin_wait_hwgroup(drive))
|
|
|
- return -EBUSY;
|
|
|
- switch (setting->data_type) {
|
|
|
- case TYPE_BYTE:
|
|
|
- *((u8 *) setting->data) = val;
|
|
|
- break;
|
|
|
- case TYPE_SHORT:
|
|
|
- *((u16 *) setting->data) = val;
|
|
|
- break;
|
|
|
- case TYPE_INT:
|
|
|
- *((u32 *) setting->data) = val;
|
|
|
- break;
|
|
|
- case TYPE_INTA:
|
|
|
- p = (u32 *) setting->data;
|
|
|
- for (i = 0; i < 1 << PARTN_BITS; i++, p++)
|
|
|
- *p = val;
|
|
|
- break;
|
|
|
- }
|
|
|
- spin_unlock_irq(&ide_lock);
|
|
|
- return 0;
|
|
|
-}
|
|
|
|
|
|
-static int set_io_32bit(ide_drive_t *drive, int arg)
|
|
|
-{
|
|
|
drive->io_32bit = arg;
|
|
|
#ifdef CONFIG_BLK_DEV_DTC2278
|
|
|
if (HWIF(drive)->chipset == ide_dtc2278)
|
|
@@ -1121,12 +870,28 @@ static int set_io_32bit(ide_drive_t *drive, int arg)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int set_using_dma (ide_drive_t *drive, int arg)
|
|
|
+static int set_ksettings(ide_drive_t *drive, int arg)
|
|
|
+{
|
|
|
+ if (arg < 0 || arg > 1)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (ide_spin_wait_hwgroup(drive))
|
|
|
+ return -EBUSY;
|
|
|
+ drive->keep_settings = arg;
|
|
|
+ spin_unlock_irq(&ide_lock);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+int set_using_dma(ide_drive_t *drive, int arg)
|
|
|
{
|
|
|
#ifdef CONFIG_BLK_DEV_IDEDMA
|
|
|
ide_hwif_t *hwif = drive->hwif;
|
|
|
int err = -EPERM;
|
|
|
|
|
|
+ if (arg < 0 || arg > 1)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
if (!drive->id || !(drive->id->capability & 1))
|
|
|
goto out;
|
|
|
|
|
@@ -1159,14 +924,20 @@ static int set_using_dma (ide_drive_t *drive, int arg)
|
|
|
out:
|
|
|
return err;
|
|
|
#else
|
|
|
+ if (arg < 0 || arg > 1)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
return -EPERM;
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-static int set_pio_mode (ide_drive_t *drive, int arg)
|
|
|
+int set_pio_mode(ide_drive_t *drive, int arg)
|
|
|
{
|
|
|
struct request rq;
|
|
|
|
|
|
+ if (arg < 0 || arg > 255)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
if (!HWIF(drive)->tuneproc)
|
|
|
return -ENOSYS;
|
|
|
if (drive->special.b.set_tune)
|
|
@@ -1178,42 +949,20 @@ static int set_pio_mode (ide_drive_t *drive, int arg)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int set_xfer_rate (ide_drive_t *drive, int arg)
|
|
|
+static int set_unmaskirq(ide_drive_t *drive, int arg)
|
|
|
{
|
|
|
- int err = ide_wait_cmd(drive,
|
|
|
- WIN_SETFEATURES, (u8) arg,
|
|
|
- SETFEATURES_XFER, 0, NULL);
|
|
|
+ if (drive->no_unmask)
|
|
|
+ return -EPERM;
|
|
|
|
|
|
- if (!err && arg) {
|
|
|
- ide_set_xfer_rate(drive, (u8) arg);
|
|
|
- ide_driveid_update(drive);
|
|
|
- }
|
|
|
- return err;
|
|
|
-}
|
|
|
+ if (arg < 0 || arg > 1)
|
|
|
+ return -EINVAL;
|
|
|
|
|
|
-/**
|
|
|
- * ide_add_generic_settings - generic ide settings
|
|
|
- * @drive: drive being configured
|
|
|
- *
|
|
|
- * Add the generic parts of the system settings to the /proc files and
|
|
|
- * ioctls for this IDE device. The caller must not be holding the
|
|
|
- * ide_setting_sem.
|
|
|
- */
|
|
|
+ if (ide_spin_wait_hwgroup(drive))
|
|
|
+ return -EBUSY;
|
|
|
+ drive->unmask = arg;
|
|
|
+ spin_unlock_irq(&ide_lock);
|
|
|
|
|
|
-void ide_add_generic_settings (ide_drive_t *drive)
|
|
|
-{
|
|
|
-/*
|
|
|
- * drive setting name read/write access read ioctl write ioctl data type min max mul_factor div_factor data pointer set function
|
|
|
- */
|
|
|
- __ide_add_setting(drive, "io_32bit", drive->no_io_32bit ? SETTING_READ : SETTING_RW, HDIO_GET_32BIT, HDIO_SET_32BIT, TYPE_BYTE, 0, 1 + (SUPPORT_VLB_SYNC << 1), 1, 1, &drive->io_32bit, set_io_32bit, 0);
|
|
|
- __ide_add_setting(drive, "keepsettings", SETTING_RW, HDIO_GET_KEEPSETTINGS, HDIO_SET_KEEPSETTINGS, TYPE_BYTE, 0, 1, 1, 1, &drive->keep_settings, NULL, 0);
|
|
|
- __ide_add_setting(drive, "nice1", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->nice1, NULL, 0);
|
|
|
- __ide_add_setting(drive, "pio_mode", SETTING_WRITE, -1, HDIO_SET_PIO_MODE, TYPE_BYTE, 0, 255, 1, 1, NULL, set_pio_mode, 0);
|
|
|
- __ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL, 0);
|
|
|
- __ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma, 0);
|
|
|
- __ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->init_speed, NULL, 0);
|
|
|
- __ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 70, 1, 1, &drive->current_speed, set_xfer_rate, 0);
|
|
|
- __ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL, 0);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -1285,27 +1034,23 @@ static int generic_ide_resume(struct device *dev)
|
|
|
int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
|
|
|
unsigned int cmd, unsigned long arg)
|
|
|
{
|
|
|
- ide_settings_t *setting;
|
|
|
+ unsigned long flags;
|
|
|
ide_driver_t *drv;
|
|
|
- int err = 0;
|
|
|
void __user *p = (void __user *)arg;
|
|
|
+ int err = 0, (*setfunc)(ide_drive_t *, int);
|
|
|
+ u8 *val;
|
|
|
|
|
|
- down(&ide_setting_sem);
|
|
|
- if ((setting = ide_find_setting_by_ioctl(drive, cmd)) != NULL) {
|
|
|
- if (cmd == setting->read_ioctl) {
|
|
|
- err = ide_read_setting(drive, setting);
|
|
|
- up(&ide_setting_sem);
|
|
|
- return err >= 0 ? put_user(err, (long __user *)arg) : err;
|
|
|
- } else {
|
|
|
- if (bdev != bdev->bd_contains)
|
|
|
- err = -EINVAL;
|
|
|
- else
|
|
|
- err = ide_write_setting(drive, setting, arg);
|
|
|
- up(&ide_setting_sem);
|
|
|
- return err;
|
|
|
- }
|
|
|
+ switch (cmd) {
|
|
|
+ case HDIO_GET_32BIT: val = &drive->io_32bit; goto read_val;
|
|
|
+ case HDIO_GET_KEEPSETTINGS: val = &drive->keep_settings; goto read_val;
|
|
|
+ case HDIO_GET_UNMASKINTR: val = &drive->unmask; goto read_val;
|
|
|
+ case HDIO_GET_DMA: val = &drive->using_dma; goto read_val;
|
|
|
+ case HDIO_SET_32BIT: setfunc = set_io_32bit; goto set_val;
|
|
|
+ case HDIO_SET_KEEPSETTINGS: setfunc = set_ksettings; goto set_val;
|
|
|
+ case HDIO_SET_PIO_MODE: setfunc = set_pio_mode; goto set_val;
|
|
|
+ case HDIO_SET_UNMASKINTR: setfunc = set_unmaskirq; goto set_val;
|
|
|
+ case HDIO_SET_DMA: setfunc = set_using_dma; goto set_val;
|
|
|
}
|
|
|
- up(&ide_setting_sem);
|
|
|
|
|
|
switch (cmd) {
|
|
|
case HDIO_OBSOLETE_IDENTITY:
|
|
@@ -1359,7 +1104,7 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
|
|
|
ide_init_hwif_ports(&hw, (unsigned long) args[0],
|
|
|
(unsigned long) args[1], NULL);
|
|
|
hw.irq = args[2];
|
|
|
- if (ide_register_hw(&hw, NULL) == -1)
|
|
|
+ if (ide_register_hw(&hw, 0, NULL) == -1)
|
|
|
return -EIO;
|
|
|
return 0;
|
|
|
}
|
|
@@ -1434,6 +1179,28 @@ int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device
|
|
|
default:
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
+
|
|
|
+read_val:
|
|
|
+ down(&ide_setting_sem);
|
|
|
+ spin_lock_irqsave(&ide_lock, flags);
|
|
|
+ err = *val;
|
|
|
+ spin_unlock_irqrestore(&ide_lock, flags);
|
|
|
+ up(&ide_setting_sem);
|
|
|
+ return err >= 0 ? put_user(err, (long __user *)arg) : err;
|
|
|
+
|
|
|
+set_val:
|
|
|
+ if (bdev != bdev->bd_contains)
|
|
|
+ err = -EINVAL;
|
|
|
+ else {
|
|
|
+ if (!capable(CAP_SYS_ADMIN))
|
|
|
+ err = -EACCES;
|
|
|
+ else {
|
|
|
+ down(&ide_setting_sem);
|
|
|
+ err = setfunc(drive, arg);
|
|
|
+ up(&ide_setting_sem);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
EXPORT_SYMBOL(generic_ide_ioctl);
|
|
@@ -1566,13 +1333,13 @@ static int __init ide_setup(char *s)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_BLK_DEV_IDEPCI
|
|
|
+#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
|
|
|
if (!strcmp(s, "ide=reverse")) {
|
|
|
ide_scan_direction = 1;
|
|
|
printk(" : Enabled support for IDE inverse scan order.\n");
|
|
|
return 1;
|
|
|
}
|
|
|
-#endif /* CONFIG_BLK_DEV_IDEPCI */
|
|
|
+#endif
|
|
|
|
|
|
#ifdef CONFIG_BLK_DEV_IDEACPI
|
|
|
if (!strcmp(s, "ide=noacpi")) {
|
|
@@ -1832,9 +1599,9 @@ extern void __init h8300_ide_init(void);
|
|
|
*/
|
|
|
static void __init probe_for_hwifs (void)
|
|
|
{
|
|
|
-#ifdef CONFIG_BLK_DEV_IDEPCI
|
|
|
+#ifdef CONFIG_IDEPCI_PCIBUS_ORDER
|
|
|
ide_scan_pcibus(ide_scan_direction);
|
|
|
-#endif /* CONFIG_BLK_DEV_IDEPCI */
|
|
|
+#endif
|
|
|
|
|
|
#ifdef CONFIG_ETRAX_IDE
|
|
|
{
|
|
@@ -1892,54 +1659,6 @@ static void __init probe_for_hwifs (void)
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-void ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
|
|
|
-{
|
|
|
-#ifdef CONFIG_PROC_FS
|
|
|
- ide_add_proc_entries(drive->proc, driver->proc, drive);
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-EXPORT_SYMBOL(ide_register_subdriver);
|
|
|
-
|
|
|
-/**
|
|
|
- * ide_unregister_subdriver - disconnect drive from driver
|
|
|
- * @drive: drive to unplug
|
|
|
- * @driver: driver
|
|
|
- *
|
|
|
- * Disconnect a drive from the driver it was attached to and then
|
|
|
- * clean up the various proc files and other objects attached to it.
|
|
|
- *
|
|
|
- * Takes ide_setting_sem and ide_lock.
|
|
|
- * Caller must hold none of the locks.
|
|
|
- */
|
|
|
-
|
|
|
-void ide_unregister_subdriver(ide_drive_t *drive, ide_driver_t *driver)
|
|
|
-{
|
|
|
- unsigned long flags;
|
|
|
-
|
|
|
-#ifdef CONFIG_PROC_FS
|
|
|
- ide_remove_proc_entries(drive->proc, driver->proc);
|
|
|
-#endif
|
|
|
- down(&ide_setting_sem);
|
|
|
- spin_lock_irqsave(&ide_lock, flags);
|
|
|
- /*
|
|
|
- * ide_setting_sem protects the settings list
|
|
|
- * ide_lock protects the use of settings
|
|
|
- *
|
|
|
- * so we need to hold both, ide_settings_sem because we want to
|
|
|
- * modify the settings list, and ide_lock because we cannot take
|
|
|
- * a setting out that is being used.
|
|
|
- *
|
|
|
- * OTOH both ide_{read,write}_setting are only ever used under
|
|
|
- * ide_setting_sem.
|
|
|
- */
|
|
|
- auto_remove_settings(drive);
|
|
|
- spin_unlock_irqrestore(&ide_lock, flags);
|
|
|
- up(&ide_setting_sem);
|
|
|
-}
|
|
|
-
|
|
|
-EXPORT_SYMBOL(ide_unregister_subdriver);
|
|
|
-
|
|
|
/*
|
|
|
* Probe module
|
|
|
*/
|
|
@@ -2071,9 +1790,7 @@ static int __init ide_init(void)
|
|
|
|
|
|
init_ide_data();
|
|
|
|
|
|
-#ifdef CONFIG_PROC_FS
|
|
|
- proc_ide_root = proc_mkdir("ide", NULL);
|
|
|
-#endif
|
|
|
+ proc_ide_create();
|
|
|
|
|
|
#ifdef CONFIG_BLK_DEV_ALI14XX
|
|
|
if (probe_ali14xx)
|
|
@@ -2096,14 +1813,9 @@ static int __init ide_init(void)
|
|
|
(void)qd65xx_init();
|
|
|
#endif
|
|
|
|
|
|
- initializing = 1;
|
|
|
/* Probe for special PCI and other "known" interface chipsets. */
|
|
|
probe_for_hwifs();
|
|
|
- initializing = 0;
|
|
|
|
|
|
-#ifdef CONFIG_PROC_FS
|
|
|
- proc_ide_create();
|
|
|
-#endif
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -2143,9 +1855,7 @@ void __exit cleanup_module (void)
|
|
|
pnpide_exit();
|
|
|
#endif
|
|
|
|
|
|
-#ifdef CONFIG_PROC_FS
|
|
|
proc_ide_destroy();
|
|
|
-#endif
|
|
|
|
|
|
bus_unregister(&ide_bus_type);
|
|
|
}
|