vserver 1.9.3
[linux-2.6.git] / drivers / ide / ide.c
index e99d9ec..c57bd4c 100644 (file)
@@ -320,13 +320,19 @@ static void __init init_ide_data (void)
 #endif
 }
 
-/*
- * ide_system_bus_speed() returns what we think is the system VESA/PCI
- * bus speed (in MHz).  This is used for calculating interface PIO timings.
- * The default is 40 for known PCI systems, 50 otherwise.
- * The "idebus=xx" parameter can be used to override this value.
- * The actual value to be used is computed/displayed the first time through.
+/**
+ *     ide_system_bus_speed    -       guess bus speed
+ *
+ *     ide_system_bus_speed() returns what we think is the system VESA/PCI
+ *     bus speed (in MHz). This is used for calculating interface PIO timings.
+ *     The default is 40 for known PCI systems, 50 otherwise.
+ *     The "idebus=xx" parameter can be used to override this value.
+ *     The actual value to be used is computed/displayed the first time
+ *     through. Drivers should only use this as a last resort.
+ *
+ *     Returns a guessed speed in MHz.
  */
+
 int ide_system_bus_speed (void)
 {
        if (!system_bus_speed) {
@@ -347,10 +353,15 @@ int ide_system_bus_speed (void)
        return system_bus_speed;
 }
 
-/*
- * current_capacity() returns the capacity (in sectors) of a drive
- * according to its current geometry/LBA settings.
+/**
+ *     current_capacity        -       drive capacity
+ *     @drive: drive to query
+ *
+ *     Return the current capacity (in sectors) of a drive according to
+ *     its current geometry/LBA settings. Empty removables are reported
+ *     as size zero.
  */
+
 sector_t current_capacity (ide_drive_t *drive)
 {
        if (!drive->present)
@@ -360,9 +371,17 @@ sector_t current_capacity (ide_drive_t *drive)
 
 EXPORT_SYMBOL(current_capacity);
 
-/*
- * Error reporting, in human readable form (luxurious, but a memory hog).
+/**
+ *     ide_dump_status         -       translate ATA error
+ *     @drive: drive the error occured on
+ *     @msg: information string
+ *     @stat: status byte
+ *
+ *     Error reporting, in human readable form (luxurious, but a memory hog).
+ *     Combines the drive name, message and status byte to provide a
+ *     user understandable explanation of the device error.
  */
+
 u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 {
        ide_hwif_t *hwif = HWIF(drive);
@@ -371,7 +390,6 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
 
        local_irq_set(flags);
        printk(KERN_WARNING "%s: %s: status=0x%02x", drive->name, msg, stat);
-#if FANCY_STATUS_DUMPS
        printk(" { ");
        if (stat & BUSY_STAT) {
                printk("Busy ");
@@ -385,12 +403,10 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
                if (stat & ERR_STAT)    printk("Error ");
        }
        printk("}");
-#endif /* FANCY_STATUS_DUMPS */
        printk("\n");
        if ((stat & (BUSY_STAT|ERR_STAT)) == ERR_STAT) {
                err = hwif->INB(IDE_ERROR_REG);
                printk("%s: %s: error=0x%02x", drive->name, msg, err);
-#if FANCY_STATUS_DUMPS
                if (drive->media == ide_disk) {
                        printk(" { ");
                        if (err & ABRT_ERR)     printk("DriveStatusError ");
@@ -434,9 +450,34 @@ u8 ide_dump_status (ide_drive_t *drive, const char *msg, u8 stat)
                                        printk(", sector=%llu", (unsigned long long)HWGROUP(drive)->rq->sector);
                        }
                }
-#endif /* FANCY_STATUS_DUMPS */
                printk("\n");
        }
+       {
+               struct request *rq;
+               int opcode = 0x100;
+
+               spin_lock(&ide_lock);
+               rq = NULL;
+               if (HWGROUP(drive))
+                       rq = HWGROUP(drive)->rq;
+               spin_unlock(&ide_lock);
+               if (!rq)
+                       goto out;
+               if (rq->flags & (REQ_DRIVE_CMD | REQ_DRIVE_TASK)) {
+                       char *args = rq->buffer;
+                       if (args)
+                               opcode = args[0];
+               } else if (rq->flags & REQ_DRIVE_TASKFILE) {
+                       ide_task_t *args = rq->special;
+                       if (args) {
+                               task_struct_t *tf = (task_struct_t *) args->tfRegister;
+                               opcode = tf->command;
+                       }
+               }
+
+               printk("ide: failed opcode was %x\n", opcode);
+       }
+out:
        local_irq_restore(flags);
        return err;
 }
@@ -448,11 +489,17 @@ static int ide_open (struct inode * inode, struct file * filp)
        return -ENXIO;
 }
 
+/*
+ *     drives_lock protects the list of drives, drivers_lock the
+ *     list of drivers.  Currently nobody takes both at once.
+ */
+
 static spinlock_t drives_lock = SPIN_LOCK_UNLOCKED;
 static spinlock_t drivers_lock = SPIN_LOCK_UNLOCKED;
 static LIST_HEAD(drivers);
 
-/* Iterator */
+/* Iterator for the driver list. */
+
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
        struct list_head *p;
@@ -463,22 +510,26 @@ static void *m_start(struct seq_file *m, loff_t *pos)
                        return list_entry(p, ide_driver_t, drivers);
        return NULL;
 }
+
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
        struct list_head *p = ((ide_driver_t *)v)->drivers.next;
        (*pos)++;
        return p==&drivers ? NULL : list_entry(p, ide_driver_t, drivers);
 }
+
 static void m_stop(struct seq_file *m, void *v)
 {
        spin_unlock(&drivers_lock);
 }
+
 static int show_driver(struct seq_file *m, void *v)
 {
        ide_driver_t *driver = v;
        seq_printf(m, "%s version %s\n", driver->name, driver->version);
        return 0;
 }
+
 struct seq_operations ide_drivers_op = {
        .start  = m_start,
        .next   = m_next,
@@ -515,6 +566,7 @@ static struct resource* hwif_request_region(ide_hwif_t *hwif,
  *     MMIO leaves it to the controller driver,
  *     PIO will migrate this way over time.
  */
+
 int ide_hwif_request_regions(ide_hwif_t *hwif)
 {
        unsigned long addr;
@@ -564,6 +616,7 @@ control_region_busy:
  *     importantly our caller should be doing this so we need to 
  *     restructure this as a helper function for drivers.
  */
+
 void ide_hwif_release_regions(ide_hwif_t *hwif)
 {
        u32 i = 0;
@@ -581,7 +634,15 @@ void ide_hwif_release_regions(ide_hwif_t *hwif)
                        release_region(hwif->io_ports[i], 1);
 }
 
-/* restore hwif to a sane state */
+/**
+ *     ide_hwif_restore        -       restore hwif to template
+ *     @hwif: hwif to update
+ *     @tmp_hwif: template
+ *
+ *     Restore hwif to a previous state by copying most settngs
+ *     from the template.
+ */
+
 static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
 {
        hwif->hwgroup                   = tmp_hwif->hwgroup;
@@ -702,18 +763,13 @@ static void ide_hwif_restore(ide_hwif_t *hwif, ide_hwif_t *tmp_hwif)
 void ide_unregister(unsigned int index)
 {
        ide_drive_t *drive;
-       ide_hwif_t *hwif, *g, *tmp_hwif;
+       ide_hwif_t *hwif, *g;
+       static ide_hwif_t tmp_hwif; /* protected by ide_cfg_sem */
        ide_hwgroup_t *hwgroup;
        int irq_count = 0, unit, i;
 
        BUG_ON(index >= MAX_HWIFS);
 
-       tmp_hwif = kmalloc(sizeof(*tmp_hwif), GFP_KERNEL|__GFP_NOFAIL);
-       if (!tmp_hwif) {
-               printk(KERN_ERR "%s: unable to allocate memory\n", __FUNCTION__);
-               return;
-       }
-
        BUG_ON(in_interrupt());
        BUG_ON(irqs_disabled());
        down(&ide_cfg_sem);
@@ -860,19 +916,17 @@ void ide_unregister(unsigned int index)
        }
 
        /* copy original settings */
-       *tmp_hwif = *hwif;
+       tmp_hwif = *hwif;
 
        /* restore hwif data to pristine status */
        init_hwif_data(hwif, index);
        init_hwif_default(hwif, index);
 
-       ide_hwif_restore(hwif, tmp_hwif);
+       ide_hwif_restore(hwif, &tmp_hwif);
 
 abort:
        spin_unlock_irq(&ide_lock);
        up(&ide_cfg_sem);
-
-       kfree(tmp_hwif);
 }
 
 EXPORT_SYMBOL(ide_unregister);
@@ -931,10 +985,17 @@ void ide_setup_ports (    hw_regs_t *hw,
  */
 }
 
-/*
- * Register an IDE interface, specifying exactly the registers etc
- * Set init=1 iff calling before probes have taken place.
+/**
+ *     ide_register_hw         -       register IDE interface
+ *     @hw: hardware registers
+ *     @hwifp: pointer to returned hwif
+ *
+ *     Register an IDE interface, specifying exactly the registers etc.
+ *     Set init=1 iff calling before probes have taken place.
+ *
+ *     Returns -1 on error.
  */
+
 int ide_register_hw (hw_regs_t *hw, ide_hwif_t **hwifp)
 {
        int index, retry = 1;
@@ -1188,6 +1249,15 @@ int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting)
        return val;
 }
 
+/**
+ *     ide_spin_wait_hwgroup   -       wait for group
+ *     @drive: drive in the group
+ *
+ *     Wait for an IDE device group to go non busy and then return
+ *     holding the ide_lock which guards the hwgroup->busy status
+ *     and right to use it.
+ */
+
 int ide_spin_wait_hwgroup (ide_drive_t *drive)
 {
        ide_hwgroup_t *hwgroup = HWGROUP(drive);
@@ -1229,6 +1299,7 @@ EXPORT_SYMBOL(ide_spin_wait_hwgroup);
  *     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 i;
@@ -1322,22 +1393,14 @@ static int set_xfer_rate (ide_drive_t *drive, int arg)
        return err;
 }
 
-int ide_atapi_to_scsi (ide_drive_t *drive, int arg)
-{
-       if (drive->media == ide_disk) {
-               drive->scsi = 0;
-               return 0;
-       }
-
-       if (DRIVER(drive)->cleanup(drive)) {
-               drive->scsi = 0;
-               return 0;
-       }
-
-       drive->scsi = (u8) arg;
-       ata_attach(drive);
-       return 0;
-}
+/**
+ *     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.
+ */
 
 void ide_add_generic_settings (ide_drive_t *drive)
 {
@@ -1353,10 +1416,15 @@ void ide_add_generic_settings (ide_drive_t *drive)
        ide_add_setting(drive,  "init_speed",           SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      70,                             1,              1,              &drive->init_speed,             NULL);
        ide_add_setting(drive,  "current_speed",        SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      70,                             1,              1,              &drive->current_speed,          set_xfer_rate);
        ide_add_setting(drive,  "number",               SETTING_RW,                                     -1,                     -1,                     TYPE_BYTE,      0,      3,                              1,              1,              &drive->dn,                     NULL);
-       if (drive->media != ide_disk)
-               ide_add_setting(drive,  "ide-scsi",             SETTING_RW,                                     -1,             HDIO_SET_IDE_SCSI,              TYPE_BYTE,      0,      1,                              1,              1,              &drive->scsi,                   ide_atapi_to_scsi);
 }
 
+/**
+ *     system_bus_clock        -       clock guess
+ *
+ *     External version of the bus clock guess used by very old IDE drivers
+ *     for things like VLB timings. Should not be used.
+ */
+
 int system_bus_clock (void)
 {
        return((int) ((!system_bus_speed) ? ide_system_bus_speed() : system_bus_speed ));
@@ -1391,6 +1459,22 @@ abort:
        return 1;
 }
 
+/**
+ *     ata_attach              -       attach an ATA/ATAPI device
+ *     @drive: drive to attach
+ *
+ *     Takes a drive that is as yet not assigned to any midlayer IDE
+ *     driver (or is assigned to the default driver) and figures out
+ *     which driver would like to own it. If nobody claims the drive
+ *     then it is automatically attached to the default driver used for
+ *     unclaimed objects.
+ *
+ *     A return of zero indicates attachment to a driver, of one
+ *     attachment to the default driver.
+ *
+ *     Takes drivers_lock.
+ */
+
 int ata_attach(ide_drive_t *drive)
 {
        struct list_head *p;
@@ -2199,6 +2283,20 @@ int ide_register_subdriver(ide_drive_t *drive, ide_driver_t *driver)
 
 EXPORT_SYMBOL(ide_register_subdriver);
 
+/**
+ *     ide_unregister_subdriver        -       disconnect drive from driver
+ *     @drive: drive to unplug
+ *
+ *     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, ide_lock and drives_lock.
+ *     Caller must hold none of the locks.
+ *
+ *     No locking versus subdriver unload because we are moving to the
+ *     default driver anyway. Wants double checking.
+ */
+
 int ide_unregister_subdriver (ide_drive_t *drive)
 {
        unsigned long flags;
@@ -2234,6 +2332,17 @@ static int ide_drive_remove(struct device * dev)
        return 0;
 }
 
+/**
+ *     ide_register_driver     -       register IDE device driver
+ *     @driver: the IDE device driver
+ *
+ *     Register a new device driver and then scan the devices
+ *     on the IDE bus in case any should be attached to the
+ *     driver we have just registered.  If so attach them.
+ *
+ *     Takes drivers_lock and drives_lock.
+ */
+
 int ide_register_driver(ide_driver_t *driver)
 {
        struct list_head list;
@@ -2265,6 +2374,17 @@ int ide_register_driver(ide_driver_t *driver)
 
 EXPORT_SYMBOL(ide_register_driver);
 
+/**
+ *     ide_unregister_driver   -       unregister IDE device driver
+ *     @driver: the IDE device driver
+ *
+ *     Called when a driver module is being unloaded. We reattach any
+ *     devices to whatever driver claims them next (typically the default
+ *     driver).
+ *
+ *     Takes drivers_lock and called functions will take ide_setting_sem.
+ */
+
 void ide_unregister_driver(ide_driver_t *driver)
 {
        ide_drive_t *drive;