Commit 3bd271cd authored by Martin Dalecki's avatar Martin Dalecki Committed by Jeff Garzik

[PATCH] 2.5.29 IDE 108

 - typedef unsigned char byte; is finally gone. Everything using it should
   be just ported to u8 if I missed some place where it still gets used.

 - Next round of parameter parsing cleanups by Gerald Champagne.
   Adjusted a bit to harmonize with  hd.c.

 - Move IDE register bitfields declarations over from hdparm.h to
   ide.h.

 - Declare constants needed by hd.c directly there. Those are standard
   values not subject to change and we prefer a bit of code duplication
   in favour of making the two drivers independant from each other.

 - Move everything not ioctl related away from hdreg.h to ide.h.
   This header is in effect not private to the ATA code and should
   therefore not contain stuff only usefull there.
parent 12949f5d
/* /*
* linux/drivers/ide/hd.c
*
* Copyright (C) 1991, 1992 Linus Torvalds * Copyright (C) 1991, 1992 Linus Torvalds
*/ *
/*
* This is the low-level hd interrupt support. It traverses the * This is the low-level hd interrupt support. It traverses the
* request-list, using interrupts to jump between functions. As * request-list, using interrupts to jump between functions. As
* all the functions are called within interrupts, we may not * all the functions are called within interrupts, we may not
* sleep. Special care is recommended. * sleep. Special care is recommended.
* *
* modified by Drew Eckhardt to check nr of hd's from the CMOS. * modified by Drew Eckhardt to check nr of hd's from the CMOS.
* *
* Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug * Thanks to Branko Lankester, lankeste@fwi.uva.nl, who found a bug
...@@ -26,10 +22,10 @@ ...@@ -26,10 +22,10 @@
* Bugfix: max_sectors must be <= 255 or the wheels tend to come * Bugfix: max_sectors must be <= 255 or the wheels tend to come
* off in a hurry once you queue things up - Paul G. 02/2001 * off in a hurry once you queue things up - Paul G. 02/2001
*/ */
/* Uncomment the following if you want verbose error reports. */ /* Uncomment the following if you want verbose error reports. */
/* #define VERBOSE_ERRORS */ /* #define VERBOSE_ERRORS */
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/signal.h> #include <linux/signal.h>
#include <linux/sched.h> #include <linux/sched.h>
...@@ -37,7 +33,6 @@ ...@@ -37,7 +33,6 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/devfs_fs_kernel.h> #include <linux/devfs_fs_kernel.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/hdreg.h>
#include <linux/genhd.h> #include <linux/genhd.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -45,6 +40,7 @@ ...@@ -45,6 +40,7 @@
#include <linux/mc146818rtc.h> /* CMOS defines */ #include <linux/mc146818rtc.h> /* CMOS defines */
#include <linux/init.h> #include <linux/init.h>
#include <linux/blkpg.h> #include <linux/blkpg.h>
#include <linux/hdreg.h>
#define REALLY_SLOW_IO #define REALLY_SLOW_IO
#include <asm/system.h> #include <asm/system.h>
...@@ -55,6 +51,15 @@ ...@@ -55,6 +51,15 @@
#define DEVICE_NR(device) (minor(device)>>6) #define DEVICE_NR(device) (minor(device)>>6)
#include <linux/blk.h> #include <linux/blk.h>
/* ATA commands we use.
*/
#define WIN_SPECIFY 0x91 /* set drive geometry translation */
#define WIN_RESTORE 0x10
#define WIN_READ 0x20 /* 28-Bit */
#define WIN_WRITE 0x30 /* 28-Bit */
#define HD_IRQ 14 /* the standard disk interrupt */
#ifdef __arm__ #ifdef __arm__
#undef HD_IRQ #undef HD_IRQ
#endif #endif
...@@ -63,6 +68,45 @@ ...@@ -63,6 +68,45 @@
#define HD_IRQ IRQ_HARDDISK #define HD_IRQ IRQ_HARDDISK
#endif #endif
/* Hd controller regster ports */
#define HD_DATA 0x1f0 /* _CTL when writing */
#define HD_ERROR 0x1f1 /* see err-bits */
#define HD_NSECTOR 0x1f2 /* nr of sectors to read/write */
#define HD_SECTOR 0x1f3 /* starting sector */
#define HD_LCYL 0x1f4 /* starting cylinder */
#define HD_HCYL 0x1f5 /* high byte of starting cyl */
#define HD_CURRENT 0x1f6 /* 101dhhhh , d=drive, hhhh=head */
#define HD_STATUS 0x1f7 /* see status-bits */
#define HD_FEATURE HD_ERROR /* same io address, read=error, write=feature */
#define HD_PRECOMP HD_FEATURE /* obsolete use of this port - predates IDE */
#define HD_COMMAND HD_STATUS /* same io address, read=status, write=cmd */
#define HD_CMD 0x3f6 /* used for resets */
#define HD_ALTSTATUS 0x3f6 /* same as HD_STATUS but doesn't clear irq */
/* Bits of HD_STATUS */
#define ERR_STAT 0x01
#define INDEX_STAT 0x02
#define ECC_STAT 0x04 /* Corrected error */
#define DRQ_STAT 0x08
#define SEEK_STAT 0x10
#define SERVICE_STAT SEEK_STAT
#define WRERR_STAT 0x20
#define READY_STAT 0x40
#define BUSY_STAT 0x80
/* Bits for HD_ERROR */
#define MARK_ERR 0x01 /* Bad address mark */
#define TRK0_ERR 0x02 /* couldn't find track 0 */
#define ABRT_ERR 0x04 /* Command aborted */
#define MCR_ERR 0x08 /* media change request */
#define ID_ERR 0x10 /* ID field not found */
#define MC_ERR 0x20 /* media changed */
#define ECC_ERR 0x40 /* Uncorrectable ECC error */
#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED; static spinlock_t hd_lock = SPIN_LOCK_UNLOCKED;
static int revalidate_hddisk(kdev_t, int); static int revalidate_hddisk(kdev_t, int);
...@@ -162,12 +206,9 @@ void __init hd_setup(char *str, int *ints) ...@@ -162,12 +206,9 @@ void __init hd_setup(char *str, int *ints)
static void dump_status (const char *msg, unsigned int stat) static void dump_status (const char *msg, unsigned int stat)
{ {
unsigned long flags;
char devc; char devc;
devc = !blk_queue_empty(QUEUE) ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?'; devc = !blk_queue_empty(QUEUE) ? 'a' + DEVICE_NR(CURRENT->rq_dev) : '?';
save_flags (flags);
sti();
#ifdef VERBOSE_ERRORS #ifdef VERBOSE_ERRORS
printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff); printk("hd%c: %s: status=0x%02x { ", devc, msg, stat & 0xff);
if (stat & BUSY_STAT) printk("Busy "); if (stat & BUSY_STAT) printk("Busy ");
...@@ -207,8 +248,7 @@ static void dump_status (const char *msg, unsigned int stat) ...@@ -207,8 +248,7 @@ static void dump_status (const char *msg, unsigned int stat)
hd_error = inb(HD_ERROR); hd_error = inb(HD_ERROR);
printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff); printk("hd%c: %s: error=0x%02x.\n", devc, msg, hd_error & 0xff);
} }
#endif /* verbose errors */ #endif
restore_flags (flags);
} }
void check_status(void) void check_status(void)
...@@ -467,7 +507,7 @@ static void write_intr(void) ...@@ -467,7 +507,7 @@ static void write_intr(void)
if (i > 0) { if (i > 0) {
SET_HANDLER(&write_intr); SET_HANDLER(&write_intr);
outsw(HD_DATA,CURRENT->buffer,256); outsw(HD_DATA,CURRENT->buffer,256);
sti(); local_irq_enable();
} else { } else {
#if (HD_DELAY > 0) #if (HD_DELAY > 0)
last_req = read_timer(); last_req = read_timer();
...@@ -500,7 +540,7 @@ static void hd_times_out(unsigned long dummy) ...@@ -500,7 +540,7 @@ static void hd_times_out(unsigned long dummy)
return; return;
disable_irq(HD_IRQ); disable_irq(HD_IRQ);
sti(); local_irq_enable();
reset = 1; reset = 1;
dev = DEVICE_NR(CURRENT->rq_dev); dev = DEVICE_NR(CURRENT->rq_dev);
printk("hd%c: timeout\n", dev+'a'); printk("hd%c: timeout\n", dev+'a');
...@@ -510,7 +550,7 @@ static void hd_times_out(unsigned long dummy) ...@@ -510,7 +550,7 @@ static void hd_times_out(unsigned long dummy)
#endif #endif
end_request(CURRENT, 0); end_request(CURRENT, 0);
} }
cli(); local_irq_disable();
hd_request(); hd_request();
enable_irq(HD_IRQ); enable_irq(HD_IRQ);
} }
...@@ -548,7 +588,7 @@ static void hd_request(void) ...@@ -548,7 +588,7 @@ static void hd_request(void)
return; return;
repeat: repeat:
del_timer(&device_timer); del_timer(&device_timer);
sti(); local_irq_enable();
if (blk_queue_empty(QUEUE)) { if (blk_queue_empty(QUEUE)) {
do_hd = NULL; do_hd = NULL;
...@@ -556,7 +596,7 @@ static void hd_request(void) ...@@ -556,7 +596,7 @@ static void hd_request(void)
} }
if (reset) { if (reset) {
cli(); local_irq_disable();
reset_hd(); reset_hd();
return; return;
} }
...@@ -688,7 +728,7 @@ static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs) ...@@ -688,7 +728,7 @@ static void hd_interrupt(int irq, void *dev_id, struct pt_regs *regs)
if (!handler) if (!handler)
handler = unexpected_hd_interrupt; handler = unexpected_hd_interrupt;
handler(); handler();
sti(); local_irq_enable();
} }
static struct block_device_operations hd_fops = { static struct block_device_operations hd_fops = {
......
...@@ -305,8 +305,9 @@ ...@@ -305,8 +305,9 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/cdrom.h> #include <linux/cdrom.h>
#include <linux/ide.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -94,9 +94,10 @@ ...@@ -94,9 +94,10 @@
#include <linux/genhd.h> #include <linux/genhd.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/cdrom.h> #include <linux/cdrom.h>
#include <linux/buffer_head.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/atapi.h> #include <linux/atapi.h>
#include <linux/buffer_head.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/irq.h> #include <asm/irq.h>
......
...@@ -550,7 +550,8 @@ static void __init hpt374_device_order_fixup (struct pci_dev *dev, struct ata_pc ...@@ -550,7 +550,8 @@ static void __init hpt374_device_order_fixup (struct pci_dev *dev, struct ata_pc
if (!dev2) { if (!dev2) {
return; return;
} else { } else {
byte irq = 0, irq2 = 0; u8 irq = 0;
u8 irq2 = 0;
pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq); pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2); pci_read_config_byte(dev2, PCI_INTERRUPT_LINE, &irq2);
if (irq != irq2) { if (irq != irq2) {
......
...@@ -419,9 +419,10 @@ ...@@ -419,9 +419,10 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/buffer_head.h>
#include <linux/hdreg.h>
#include <linux/ide.h> #include <linux/ide.h>
#include <linux/atapi.h> #include <linux/atapi.h>
#include <linux/buffer_head.h>
#include <asm/byteorder.h> #include <asm/byteorder.h>
#include <asm/irq.h> #include <asm/irq.h>
...@@ -1249,7 +1250,7 @@ char *idetape_sense_key_verbose(u8 idetape_sense_key) ...@@ -1249,7 +1250,7 @@ char *idetape_sense_key_verbose(u8 idetape_sense_key)
} }
} }
char *idetape_command_key_verbose (byte idetape_command_key) char *idetape_command_key_verbose(u8 idetape_command_key)
{ {
switch (idetape_command_key) { switch (idetape_command_key) {
case IDETAPE_TEST_UNIT_READY_CMD: return("TEST_UNIT_READY_CMD"); case IDETAPE_TEST_UNIT_READY_CMD: return("TEST_UNIT_READY_CMD");
...@@ -1439,7 +1440,7 @@ static void idetape_analyze_error(struct ata_device *drive, atapi_request_sense_ ...@@ -1439,7 +1440,7 @@ static void idetape_analyze_error(struct ata_device *drive, atapi_request_sense_
# if IDETAPE_DEBUG_LOG_VERBOSE # if IDETAPE_DEBUG_LOG_VERBOSE
if (tape->debug_level >= 1) if (tape->debug_level >= 1)
printk (KERN_INFO "ide-tape: pc = %s, sense key = %x, asc = %x, ascq = %x\n", printk (KERN_INFO "ide-tape: pc = %s, sense key = %x, asc = %x, ascq = %x\n",
idetape_command_key_verbose((byte) pc->c[0]), idetape_command_key_verbose(pc->c[0]),
result->sense_key, result->sense_key,
result->asc, result->asc,
result->ascq); result->ascq);
...@@ -2166,7 +2167,7 @@ static void idetape_pc_callback(struct ata_device *drive, struct request *rq) ...@@ -2166,7 +2167,7 @@ static void idetape_pc_callback(struct ata_device *drive, struct request *rq)
/* /*
* A mode sense command is used to "sense" tape parameters. * A mode sense command is used to "sense" tape parameters.
*/ */
static void idetape_create_mode_sense_cmd(struct atapi_packet_command *pc, byte page_code) static void idetape_create_mode_sense_cmd(struct atapi_packet_command *pc, u8 page_code)
{ {
atapi_init_pc(pc); atapi_init_pc(pc);
pc->c[0] = IDETAPE_MODE_SENSE_CMD; pc->c[0] = IDETAPE_MODE_SENSE_CMD;
...@@ -3225,7 +3226,7 @@ static int __idetape_discard_read_pipeline(struct ata_device *drive) ...@@ -3225,7 +3226,7 @@ static int __idetape_discard_read_pipeline(struct ata_device *drive)
* of the request queue and wait for their completion. * of the request queue and wait for their completion.
* *
*/ */
static int idetape_position_tape(struct ata_device *drive, unsigned int block, byte partition, int skip) static int idetape_position_tape(struct ata_device *drive, unsigned int block, u8 partition, int skip)
{ {
idetape_tape_t *tape = drive->driver_data; idetape_tape_t *tape = drive->driver_data;
int retval; int retval;
...@@ -3981,7 +3982,7 @@ static int idetape_add_chrdev_read_request(struct ata_device *drive,int blocks) ...@@ -3981,7 +3982,7 @@ static int idetape_add_chrdev_read_request(struct ata_device *drive,int blocks)
printk (KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n"); printk (KERN_ERR "ide-tape: bug: trying to return more bytes than requested\n");
bytes_read=blocks*tape->tape_block_size; bytes_read=blocks*tape->tape_block_size;
} }
#endif /* IDETAPE_DEBUG_BUGS */ #endif
return (bytes_read); return (bytes_read);
} }
......
...@@ -33,6 +33,15 @@ ...@@ -33,6 +33,15 @@
#include "ioctl.h" #include "ioctl.h"
/* BIG GEOMETRY - dying, used only by HDIO_GETGEO_BIG_RAW */
struct hd_big_geometry {
u8 heads;
u8 sectors;
u32 cylinders;
unsigned long start;
};
/* /*
* Implement generic ioctls invoked from userspace to imlpement specific * Implement generic ioctls invoked from userspace to imlpement specific
* functionality. * functionality.
......
...@@ -191,7 +191,11 @@ static void init_hwif_data(struct ata_channel *ch, unsigned int index) ...@@ -191,7 +191,11 @@ static void init_hwif_data(struct ata_channel *ch, unsigned int index)
ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET]; ch->noprobe = !ch->io_ports[IDE_DATA_OFFSET];
#ifdef CONFIG_BLK_DEV_HD #ifdef CONFIG_BLK_DEV_HD
if (ch->io_ports[IDE_DATA_OFFSET] == HD_DATA)
/* Ignore disks for which handling by the legacy driver was requested
* by the used.
*/
if (ch->io_ports[IDE_DATA_OFFSET] == 0x1f0)
ch->noprobe = 1; /* may be overridden by ide_setup() */ ch->noprobe = 1; /* may be overridden by ide_setup() */
#endif #endif
...@@ -701,79 +705,46 @@ static void __init init_global_data(void) ...@@ -701,79 +705,46 @@ static void __init init_global_data(void)
/* /*
* This gets called VERY EARLY during initialization, to handle kernel "command * This gets called VERY EARLY during initialization, to handle kernel "command
* line" strings beginning with "hdx=" or "ide".It gets called even before the * line" strings beginning with "hdx=". It gets called even before the actual
* actual module gets initialized. * module gets initialized.
* *
* Please look at Documentation/ide.txt to see the complete list of supported * Please look at Documentation/ide.txt to see the complete list of supported
* options. * options.
*/ */
int __init ide_setup(char *s) static int __init ata_hd_setup(char *s)
{ {
int i, vals[4]; int vals[4];
struct ata_channel *ch; struct ata_channel *ch; /* FIXME: Channel parms should not be accessed in ata_hd_setup */
struct ata_device *drive; struct ata_device *drive;
unsigned int hw, unit; unsigned int hw, unit;
const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1); const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1);
const char max_ch = '0' + (MAX_HWIFS - 1);
if (!strncmp(s, "hd=", 3)) /* hd= is for hd.c driver and not us */ if (s[0] == '=') /* hd= is for hd.c driver and not us */
return 0; return 0;
if (strncmp(s,"ide",3) && printk(KERN_INFO "hd%s", s);
strncmp(s,"hd",2)) /* hdx= & hdxlun= */
return 0;
printk(KERN_INFO "ide_setup: %s", s);
init_global_data(); init_global_data();
#ifdef CONFIG_BLK_DEV_IDEDOUBLER if (s[0] >= 'a' && s[0] <= max_drive) {
if (!strcmp(s, "ide=doubler")) { static const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom",
extern int ide_doubler;
printk(KERN_INFO" : Enabled support for IDE doublers\n");
ide_doubler = 1;
return 1;
}
#endif
if (!strcmp(s, "ide=nodma")) {
printk(KERN_INFO "ATA: Prevented DMA\n");
noautodma = 1;
return 1;
}
#ifdef CONFIG_PCI
if (!strcmp(s, "ide=reverse")) {
ide_scan_direction = 1;
printk(" : Enabled support for IDE inverse scan order.\n");
return 1;
}
#endif
/*
* Look for drive options: "hdx="
*/
if (!strncmp(s, "hd", 2) && s[2] >= 'a' && s[2] <= max_drive) {
const char *hd_words[] = {"none", "noprobe", "nowerr", "cdrom",
"serialize", "autotune", "noautotune", "serialize", "autotune", "noautotune",
"slow", "flash", "remap", "noremap", "scsi", NULL}; "slow", "flash", "remap", "noremap", "scsi", NULL};
unit = s[2] - 'a'; unit = s[0] - 'a';
hw = unit / MAX_DRIVES; hw = unit / MAX_DRIVES;
unit = unit % MAX_DRIVES; unit = unit % MAX_DRIVES;
ch = &ide_hwifs[hw]; ch = &ide_hwifs[hw];
drive = &ch->drives[unit]; drive = &ch->drives[unit];
if (!strncmp(s+3, "=ide-", 5)) {
strncpy(drive->driver_req, s + 4, 9); /* Look for hdx=ide-* */
if (!strncmp(s+1, "=ide-", 5)) {
strncpy(drive->driver_req, s+2, 9);
goto done; goto done;
} }
/* /*
* Look for last lun option: "hdxlun=" * Look for last lun option: "hdxlun="
*/ */
if (!strncmp(s+3, "lun=", 4)) { if (!strncmp(s+1, "lun=", 4)) {
if (*get_options(s+7, 2, vals) || vals[0]!=1) if (*get_options(s+5, 2, vals) || vals[0]!=1)
goto bad_option; goto bad_option;
if (vals[1] >= 0 && vals[1] <= 7) { if (vals[1] >= 0 && vals[1] <= 7) {
drive->last_lun = vals[1]; drive->last_lun = vals[1];
...@@ -782,7 +753,7 @@ int __init ide_setup(char *s) ...@@ -782,7 +753,7 @@ int __init ide_setup(char *s)
printk(" -- BAD LAST LUN! Expected value from 0 to 7"); printk(" -- BAD LAST LUN! Expected value from 0 to 7");
goto done; goto done;
} }
switch (match_parm(s+3, hd_words, vals, 3)) { switch (match_parm(s+1, hd_words, vals, 3)) {
case -1: /* "none" */ case -1: /* "none" */
drive->nobios = 1; /* drop into "noprobe" */ drive->nobios = 1; /* drop into "noprobe" */
case -2: /* "noprobe" */ case -2: /* "noprobe" */
...@@ -790,16 +761,16 @@ int __init ide_setup(char *s) ...@@ -790,16 +761,16 @@ int __init ide_setup(char *s)
goto done; goto done;
case -3: /* "nowerr" */ case -3: /* "nowerr" */
drive->bad_wstat = BAD_R_STAT; drive->bad_wstat = BAD_R_STAT;
ch->noprobe = 0; ch->noprobe = 0; /* FIXME: Channel parm */
goto done; goto done;
case -4: /* "cdrom" */ case -4: /* "cdrom" */
drive->present = 1; drive->present = 1;
drive->type = ATA_ROM; drive->type = ATA_ROM;
ch->noprobe = 0; ch->noprobe = 0; /* FIXME: Channel parm */
goto done; goto done;
case -5: /* "serialize" */ case -5: /* "serialize" */
printk(" -- USE \"ide%d=serialize\" INSTEAD", hw); printk(" -- USE \"ide%d=serialize\" INSTEAD", hw);
goto do_serialize; goto bad_option;
case -6: /* "autotune" */ case -6: /* "autotune" */
drive->autotune = 1; drive->autotune = 1;
goto done; goto done;
...@@ -807,7 +778,7 @@ int __init ide_setup(char *s) ...@@ -807,7 +778,7 @@ int __init ide_setup(char *s)
drive->autotune = 2; drive->autotune = 2;
goto done; goto done;
case -8: /* "slow" */ case -8: /* "slow" */
ch->slow = 1; ch->slow = 1; /* FIXME: Channel parm */
goto done; goto done;
case -9: /* "flash" */ case -9: /* "flash" */
drive->ata_flash = 1; drive->ata_flash = 1;
...@@ -840,11 +811,63 @@ int __init ide_setup(char *s) ...@@ -840,11 +811,63 @@ int __init ide_setup(char *s)
} }
} }
bad_option:
printk(" -- BAD OPTION\n");
return 1;
done:
printk("\n");
return 1;
}
/*
* This gets called VERY EARLY during initialization, to handle kernel "command
* line" strings beginning with "ide". It gets called even before the actual
* module gets initialized.
*
* Please look at Documentation/ide.txt to see the complete list of supported
* options.
*/
int __init ide_setup(char *s)
{
int i, vals[4];
struct ata_channel *ch;
unsigned int hw;
const char max_ch = '0' + (MAX_HWIFS - 1);
printk(KERN_INFO "ide_setup: ide%s", s);
init_global_data();
#ifdef CONFIG_BLK_DEV_IDEDOUBLER
if (!strcmp(s, "=doubler")) {
extern int ide_doubler;
printk(KERN_INFO" : Enabled support for IDE doublers\n");
ide_doubler = 1;
return 1;
}
#endif
if (!strcmp(s, "=nodma")) {
printk(KERN_INFO "ATA: Prevented DMA\n");
noautodma = 1;
return 1;
}
#ifdef CONFIG_PCI
if (!strcmp(s, "=reverse")) {
ide_scan_direction = 1;
printk(" : Enabled support for IDE inverse scan order.\n");
return 1;
}
#endif
/* /*
* Look for bus speed option: "idebus=" * Look for bus speed option: "idebus="
*/ */
if (!strncmp(s, "idebus=", 7)) { if (!strncmp(s, "bus=", 4)) {
if (*get_options(s+7, 2, vals) || vals[0] != 1) if (*get_options(s+4, 2, vals) || vals[0] != 1)
goto bad_option; goto bad_option;
idebus_parameter = vals[1]; idebus_parameter = vals[1];
goto done; goto done;
...@@ -853,7 +876,7 @@ int __init ide_setup(char *s) ...@@ -853,7 +876,7 @@ int __init ide_setup(char *s)
/* /*
* Look for interface options: "idex=" * Look for interface options: "idex="
*/ */
if (!strncmp(s, "ide", 3) && s[3] >= '0' && s[3] <= max_ch) { if (s[0] >= '0' && s[0] <= max_ch) {
/* /*
* Be VERY CAREFUL changing this: note hardcoded indexes below * Be VERY CAREFUL changing this: note hardcoded indexes below
*/ */
...@@ -861,11 +884,11 @@ int __init ide_setup(char *s) ...@@ -861,11 +884,11 @@ int __init ide_setup(char *s)
"noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", NULL }; "noprobe", "serialize", "autotune", "noautotune", "reset", "dma", "ata66", NULL };
const char *ide_words[] = { const char *ide_words[] = {
"qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL }; "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", "dc4030", NULL };
hw = s[3] - '0'; hw = s[0] - '0';
ch = &ide_hwifs[hw]; ch = &ide_hwifs[hw];
switch (match_parm(s+4, ide_options, vals, 1)) { switch (match_parm(s+1, ide_options, vals, 1)) {
case -7: /* ata66 */ case -7: /* ata66 */
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
ch->udma_four = 1; ch->udma_four = 1;
...@@ -889,7 +912,6 @@ int __init ide_setup(char *s) ...@@ -889,7 +912,6 @@ int __init ide_setup(char *s)
ch->drives[1].autotune = 1; ch->drives[1].autotune = 1;
goto done; goto done;
case -2: /* "serialize" */ case -2: /* "serialize" */
do_serialize:
{ {
struct ata_channel *mate; struct ata_channel *mate;
...@@ -904,7 +926,10 @@ int __init ide_setup(char *s) ...@@ -904,7 +926,10 @@ int __init ide_setup(char *s)
goto done; goto done;
} }
i = match_parm(&s[4], ide_words, vals, 3); /*
* Check for specific chipset name
*/
i = match_parm(s+1, ide_words, vals, 3);
/* /*
* Cryptic check to ensure chipset not already set for a channel: * Cryptic check to ensure chipset not already set for a channel:
...@@ -913,7 +938,7 @@ int __init ide_setup(char *s) ...@@ -913,7 +938,7 @@ int __init ide_setup(char *s)
if (ide_hwifs[hw].chipset != ide_unknown) if (ide_hwifs[hw].chipset != ide_unknown)
goto bad_option; /* chipset already specified */ goto bad_option; /* chipset already specified */
if (i != -7 && hw != 0) if (i != -7 && hw != 0)
goto bad_channel; /* chipset drivers are for "ide0=" only */ goto bad_channel; /* chipset drivers are for "ide0=" only */
if (i != -7 && ide_hwifs[1].chipset != ide_unknown) if (i != -7 && ide_hwifs[1].chipset != ide_unknown)
goto bad_option; /* chipset for 2nd port already specified */ goto bad_option; /* chipset for 2nd port already specified */
printk("\n"); printk("\n");
...@@ -1432,8 +1457,14 @@ static int __init init_ata(void) ...@@ -1432,8 +1457,14 @@ static int __init init_ata(void)
while ((options = next) != NULL) { while ((options = next) != NULL) {
if ((next = strchr(options,' ')) != NULL) if ((next = strchr(options,' ')) != NULL)
*next++ = 0; *next++ = 0;
if (!ide_setup(options)) if (!strncmp(options,"hd",2)) {
printk(KERN_ERR "Unknown option '%s'\n", options); if (!ata_hd_setup(options+2))
printk(KERN_ERR "Unknown option '%s'\n", options);
}
else if (!strncmp(options,"ide",3)) {
if (!ide_setup(options+3))
printk(KERN_ERR "Unknown option '%s'\n", options);
}
} }
} }
return ata_module_init(); return ata_module_init();
...@@ -1457,6 +1488,7 @@ module_exit(cleanup_ata); ...@@ -1457,6 +1488,7 @@ module_exit(cleanup_ata);
#ifndef MODULE #ifndef MODULE
/* command line option parser */ /* command line option parser */
__setup("", ide_setup); __setup("ide", ide_setup);
__setup("hd", ata_hd_setup);
#endif #endif
...@@ -1082,7 +1082,12 @@ static void channel_init(struct ata_channel *ch) ...@@ -1082,7 +1082,12 @@ static void channel_init(struct ata_channel *ch)
} }
} }
#ifdef CONFIG_BLK_DEV_HD #ifdef CONFIG_BLK_DEV_HD
if (ch->irq == HD_IRQ && ch->io_ports[IDE_DATA_OFFSET] != HD_DATA) {
/* The first "legacy" HD gets distinguished by the IRQ it is attached
* to and the IO port it takes.
*/
if (ch->irq == 14 && ch->io_ports[IDE_DATA_OFFSET] != 0x1f0) {
printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", ch->name); printk("%s: CANNOT SHARE IRQ WITH OLD HARDDISK DRIVER (hd.c)\n", ch->name);
return; return;
......
...@@ -40,43 +40,47 @@ ...@@ -40,43 +40,47 @@
static void pdump (void *, int); static void pdump (void *, int);
#endif #endif
/* Bits of HD_STATUS */
#define ERR_STAT 0x01
#define DRQ_STAT 0x08
struct freecom_udata { struct freecom_udata {
__u8 buffer[64]; /* Common command block. */ u8 buffer[64]; /* Common command block. */
}; };
typedef struct freecom_udata *freecom_udata_t; typedef struct freecom_udata *freecom_udata_t;
/* All of the outgoing packets are 64 bytes long. */ /* All of the outgoing packets are 64 bytes long. */
struct freecom_cb_wrap { struct freecom_cb_wrap {
__u8 Type; /* Command type. */ u8 Type; /* Command type. */
__u8 Timeout; /* Timeout in seconds. */ u8 Timeout; /* Timeout in seconds. */
__u8 Atapi[12]; /* An ATAPI packet. */ u8 Atapi[12]; /* An ATAPI packet. */
__u8 Filler[50]; /* Padding Data. */ u8 Filler[50]; /* Padding Data. */
}; };
struct freecom_xfer_wrap { struct freecom_xfer_wrap {
__u8 Type; /* Command type. */ u8 Type; /* Command type. */
__u8 Timeout; /* Timeout in seconds. */ u8 Timeout; /* Timeout in seconds. */
__u32 Count; /* Number of bytes to transfer. */ u32 Count; /* Number of bytes to transfer. */
__u8 Pad[58]; u8 Pad[58];
} __attribute__ ((packed)); } __attribute__ ((packed));
struct freecom_ide_out { struct freecom_ide_out {
__u8 Type; /* Type + IDE register. */ u8 Type; /* Type + IDE register. */
__u8 Pad; u8 Pad;
__u16 Value; /* Value to write. */ u16 Value; /* Value to write. */
__u8 Pad2[60]; u8 Pad2[60];
}; };
struct freecom_ide_in { struct freecom_ide_in {
__u8 Type; /* Type | IDE register. */ u8 Type; /* Type | IDE register. */
__u8 Pad[63]; u8 Pad[63];
}; };
struct freecom_status { struct freecom_status {
__u8 Status; u8 Status;
__u8 Reason; u8 Reason;
__u16 Count; u16 Count;
__u8 Pad[60]; u8 Pad[60];
}; };
/* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide /* Freecom stuffs the interrupt status in the INDEX_STAT bit of the ide
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment