Commit 26af05ea authored by Jens Axboe's avatar Jens Axboe

Update of the legcay ide controller drivers. mainly the IN_BYTE -> inb()

and preparation for truly modular low level drivers.
parent 0d1e8f1f
......@@ -39,6 +39,8 @@
#undef REALLY_SLOW_IO /* most systems can safely undef this */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
......@@ -52,14 +54,20 @@
#include <asm/io.h>
#include "ide_modes.h"
#ifdef CONFIG_BLK_DEV_ALI14XX_MODULE
# define _IDE_C
# include "ide_modes.h"
# undef _IDE_C
#else
# include "ide_modes.h"
#endif /* CONFIG_BLK_DEV_ALI14XX_MODULE */
/* port addresses for auto-detection */
#define ALI_NUM_PORTS 4
static int ports[ALI_NUM_PORTS] __initdata = {0x074, 0x0f4, 0x034, 0x0e4};
/* register initialization data */
typedef struct { byte reg, data; } RegInitializer;
typedef struct { u8 reg, data; } RegInitializer;
static RegInitializer initData[] __initdata = {
{0x01, 0x0f}, {0x02, 0x00}, {0x03, 0x00}, {0x04, 0x00},
......@@ -74,7 +82,7 @@ static RegInitializer initData[] __initdata = {
#define ALI_MAX_PIO 4
/* timing parameter registers for each drive */
static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = {
static struct { u8 reg1, reg2, reg3, reg4; } regTab[4] = {
{0x03, 0x26, 0x04, 0x27}, /* drive 0 */
{0x05, 0x28, 0x06, 0x29}, /* drive 1 */
{0x2b, 0x30, 0x2c, 0x31}, /* drive 2 */
......@@ -84,24 +92,24 @@ static struct { byte reg1, reg2, reg3, reg4; } regTab[4] = {
static int basePort; /* base port address */
static int regPort; /* port for register number */
static int dataPort; /* port for register data */
static byte regOn; /* output to base port to access registers */
static byte regOff; /* output to base port to close registers */
static u8 regOn; /* output to base port to access registers */
static u8 regOff; /* output to base port to close registers */
/*------------------------------------------------------------------------*/
/*
* Read a controller register.
*/
static inline byte inReg (byte reg)
static inline u8 inReg (u8 reg)
{
outb_p(reg, regPort);
return IN_BYTE(dataPort);
return inb(dataPort);
}
/*
* Write a controller register.
*/
static void outReg (byte data, byte reg)
static void outReg (u8 data, u8 reg)
{
outb_p(reg, regPort);
outb_p(data, dataPort);
......@@ -112,11 +120,11 @@ static void outReg (byte data, byte reg)
* This function computes timing parameters
* and sets controller registers accordingly.
*/
static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
static void ali14xx_tune_drive (ide_drive_t *drive, u8 pio)
{
int driveNum;
int time1, time2;
byte param1, param2, param3, param4;
u8 param1, param2, param3, param4;
unsigned long flags;
ide_pio_data_t d;
int bus_speed = system_bus_clock();
......@@ -132,7 +140,7 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
param3 += 8;
param4 += 8;
}
printk("%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
printk(KERN_DEBUG "%s: PIO mode%d, t1=%dns, t2=%dns, cycles = %d+%d, %d+%d\n",
drive->name, pio, time1, time2, param1, param2, param3, param4);
/* stuff timing parameters into controller registers */
......@@ -153,16 +161,16 @@ static void ali14xx_tune_drive (ide_drive_t *drive, byte pio)
static int __init findPort (void)
{
int i;
byte t;
u8 t;
unsigned long flags;
local_irq_save(flags);
for (i = 0; i < ALI_NUM_PORTS; ++i) {
basePort = ports[i];
regOff = IN_BYTE(basePort);
regOff = inb(basePort);
for (regOn = 0x30; regOn <= 0x33; ++regOn) {
outb_p(regOn, basePort);
if (IN_BYTE(basePort) == regOn) {
if (inb(basePort) == regOn) {
regPort = basePort + 4;
dataPort = basePort + 8;
t = inReg(0) & 0xf0;
......@@ -184,7 +192,7 @@ static int __init findPort (void)
*/
static int __init initRegisters (void) {
RegInitializer *p;
byte t;
u8 t;
unsigned long flags;
local_irq_save(flags);
......@@ -192,21 +200,21 @@ static int __init initRegisters (void) {
for (p = initData; p->reg != 0; ++p)
outReg(p->data, p->reg);
outb_p(0x01, regPort);
t = IN_BYTE(regPort) & 0x01;
t = inb(regPort) & 0x01;
outb_p(regOff, basePort);
local_irq_restore(flags);
return t;
}
void __init init_ali14xx (void)
int __init probe_ali14xx (void)
{
/* auto-detect IDE controller port */
if (!findPort()) {
printk("\nali14xx: not found");
return;
printk(KERN_ERR "ali14xx: not found.\n");
return 1;
}
printk("\nali14xx: base= 0x%03x, regOn = 0x%02x", basePort, regOn);
printk(KERN_DEBUG "ali14xx: base= 0x%03x, regOn = 0x%02x.\n", basePort, regOn);
ide_hwifs[0].chipset = ide_ali14xx;
ide_hwifs[1].chipset = ide_ali14xx;
ide_hwifs[0].tuneproc = &ali14xx_tune_drive;
......@@ -217,7 +225,80 @@ void __init init_ali14xx (void)
/* initialize controller registers */
if (!initRegisters()) {
printk("\nali14xx: Chip initialization failed");
printk(KERN_ERR "ali14xx: Chip initialization failed.\n");
return 1;
}
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init(&ide_hwifs[0]);
probe_hwif_init(&ide_hwifs[1]);
#endif /* HWIF_PROBE_CLASSIC_METHOD */
return 0;
}
void __init ali14xx_release (void)
{
if (ide_hwifs[0].chipset != ide_ali14xx &&
ide_hwifs[1].chipset != ide_ali14xx)
return;
ide_hwifs[0].chipset = ide_unknown;
ide_hwifs[1].chipset = ide_unknown;
ide_hwifs[0].tuneproc = NULL;
ide_hwifs[1].tuneproc = NULL;
ide_hwifs[0].mate = NULL;
ide_hwifs[1].mate = NULL;
}
#ifndef MODULE
/*
* init_ali14xx:
*
* called by ide.c when parsing command line
*/
void __init init_ali14xx (void)
{
/* auto-detect IDE controller port */
if (findPort())
if (probe_ali14xx())
goto no_detect;
return;
no_detect:
printk(KERN_ERR "ali14xx: not found.\n");
ali14xx_release();
}
#else
MODULE_AUTHOR("see local file");
MODULE_DESCRIPTION("support of ALI 14XX IDE chipsets");
MODULE_LICENSE("GPL");
int __init ali14xx_mod_init(void)
{
/* auto-detect IDE controller port */
if (findPort())
if (probe_ali14xx()) {
ali14xx_release();
return -ENODEV;
}
if (ide_hwifs[0].chipset != ide_ali14xx &&
ide_hwifs[1].chipset != ide_ali14xx) {
ali14xx_release();
return -ENODEV;
}
return 0;
}
module_init(ali14xx_mod_init);
void __init ali14xx_mod_exit(void)
{
ali14xx_release();
}
module_exit(ali14xx_mod_exit);
#endif
......@@ -169,6 +169,10 @@ void __init buddha_init(void)
board = z->resource.start;
/*
* FIXME: we now have selectable mmio v/s iomio transports.
*/
if(type != BOARD_XSURF) {
if (!request_mem_region(board+BUDDHA_BASE1, 0x800, "IDE"))
continue;
......@@ -196,12 +200,16 @@ void __init buddha_init(void)
ide_setup_ports(&hw, (ide_ioreg_t)(buddha_board+buddha_bases[i]),
buddha_offsets, 0,
(ide_ioreg_t)(buddha_board+buddha_irqports[i]),
buddha_ack_intr, IRQ_AMIGA_PORTS);
buddha_ack_intr,
// budda_iops,
IRQ_AMIGA_PORTS);
} else {
ide_setup_ports(&hw, (ide_ioreg_t)(buddha_board+xsurf_bases[i]),
xsurf_offsets, 0,
(ide_ioreg_t)(buddha_board+xsurf_irqports[i]),
xsurf_ack_intr, IRQ_AMIGA_PORTS);
xsurf_ack_intr,
// xsurf_iops,
IRQ_AMIGA_PORTS);
}
index = ide_register_hw(&hw, NULL);
......
......@@ -6,6 +6,8 @@
#undef REALLY_SLOW_IO /* most systems can safely undef this */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
......@@ -19,7 +21,13 @@
#include <asm/io.h>
#include "ide_modes.h"
#ifdef CONFIG_BLK_DEV_DTC2278_MODULE
# define _IDE_C
# include "ide_modes.h"
# undef _IDE_C
#else
# include "ide_modes.h"
#endif /* CONFIG_BLK_DEV_DTC2278_MODULE */
/*
* Changing this #undef to #define may solve start up problems in some systems.
......@@ -57,20 +65,20 @@ static void sub22 (char b, char c)
int i;
for(i = 0; i < 3; ++i) {
IN_BYTE(0x3f6);
inb(0x3f6);
outb_p(b,0xb0);
IN_BYTE(0x3f6);
inb(0x3f6);
outb_p(c,0xb4);
IN_BYTE(0x3f6);
if(IN_BYTE(0xb4) == c) {
inb(0x3f6);
if(inb(0xb4) == c) {
outb_p(7,0xb0);
IN_BYTE(0x3f6);
inb(0x3f6);
return; /* success */
}
}
}
static void tune_dtc2278 (ide_drive_t *drive, byte pio)
static void tune_dtc2278 (ide_drive_t *drive, u8 pio)
{
unsigned long flags;
......@@ -95,7 +103,7 @@ static void tune_dtc2278 (ide_drive_t *drive, byte pio)
HWIF(drive)->drives[!drive->select.b.unit].io_32bit = 1;
}
void __init init_dtc2278 (void)
void __init probe_dtc2278 (void)
{
unsigned long flags;
......@@ -104,9 +112,9 @@ void __init init_dtc2278 (void)
* This enables the second interface
*/
outb_p(4,0xb0);
IN_BYTE(0x3f6);
inb(0x3f6);
outb_p(0x20,0xb4);
IN_BYTE(0x3f6);
inb(0x3f6);
#ifdef ALWAYS_SET_DTC2278_PIO_MODE
/*
* This enables PIO mode4 (3?) on the first interface
......@@ -129,4 +137,67 @@ void __init init_dtc2278 (void)
ide_hwifs[0].mate = &ide_hwifs[1];
ide_hwifs[1].mate = &ide_hwifs[0];
ide_hwifs[1].channel = 1;
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init(&ide_hwifs[0]);
probe_hwif_init(&ide_hwifs[1]);
#endif /* HWIF_PROBE_CLASSIC_METHOD */
}
void __init dtc2278_release (void)
{
if (ide_hwifs[0].chipset != ide_dtc2278 &&
ide_hwifs[1].chipset != ide_dtc2278)
return;
ide_hwifs[0].serialized = 0;
ide_hwifs[1].serialized = 0;
ide_hwifs[0].chipset = ide_unknown;
ide_hwifs[1].chipset = ide_unknown;
ide_hwifs[0].tuneproc = NULL;
ide_hwifs[0].drives[0].no_unmask = 0;
ide_hwifs[0].drives[1].no_unmask = 0;
ide_hwifs[1].drives[0].no_unmask = 0;
ide_hwifs[1].drives[1].no_unmask = 0;
ide_hwifs[0].mate = NULL;
ide_hwifs[1].mate = NULL;
}
#ifndef MODULE
/*
* init_dtc2278:
*
* called by ide.c when parsing command line
*/
void __init init_dtc2278 (void)
{
probe_dtc2278();
}
#else
MODULE_AUTHOR("See Local File");
MODULE_DESCRIPTION("support of DTC-2278 VLB IDE chipsets");
MODULE_LICENSE("GPL");
int __init dtc2278_mod_init(void)
{
probe_dtc2278();
if (ide_hwifs[0].chipset != ide_dtc2278 &&
ide_hwifs[1].chipset != ide_dtc2278) {
dtc2278_release();
return -ENODEV;
}
return 0;
}
module_init(dtc2278_mod_init);
void __init dtc2278_mod_exit(void)
{
dtc2278_release();
}
module_exit(dtc2278_mod_exit);
#endif
......@@ -59,7 +59,9 @@ void __init falconide_init(void)
int index;
ide_setup_ports(&hw, (ide_ioreg_t)ATA_HD_BASE, falconide_offsets,
0, 0, NULL, IRQ_MFP_IDE);
0, 0, NULL,
// falconide_iops,
IRQ_MFP_IDE);
index = ide_register_hw(&hw, NULL);
if (index != -1)
......
......@@ -137,6 +137,10 @@ void __init gayle_init(void)
irqport = (ide_ioreg_t)ZTWO_VADDR(GAYLE_IRQ_1200);
ack_intr = gayle_ack_intr_a1200;
}
/*
* FIXME: we now have selectable modes between mmio v/s iomio
*/
phys_base += i*GAYLE_NEXT_PORT;
res_start = ((unsigned long)phys_base) & ~(GAYLE_NEXT_PORT-1);
......@@ -149,7 +153,9 @@ void __init gayle_init(void)
ctrlport = GAYLE_HAS_CONTROL_REG ? (base + GAYLE_CONTROL) : 0;
ide_setup_ports(&hw, base, gayle_offsets,
ctrlport, irqport, ack_intr, IRQ_AMIGA_PORTS);
ctrlport, irqport, ack_intr,
// gaule_iops,
IRQ_AMIGA_PORTS);
index = ide_register_hw(&hw, NULL);
if (index != -1) {
......
......@@ -50,13 +50,6 @@
#define DEVICE_NR(device) (minor(device)>>6)
#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__
......
......@@ -38,6 +38,8 @@
#undef REALLY_SLOW_IO /* most systems can safely undef this */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
......@@ -51,7 +53,13 @@
#include <asm/io.h>
#include "ide_modes.h"
#ifdef CONFIG_BLK_DEV_HT6560B_MODULE
# define _IDE_C
# include "ide_modes.h"
# undef _IDE_C
#else
# include "ide_modes.h"
#endif /* CONFIG_BLK_DEV_HT6560B_MODULE */
/* #define DEBUG */ /* remove comments for DEBUG messages */
......@@ -68,7 +76,7 @@
* bit3 (0x08): "1" 3 cycle time, "0" 2 cycle time (?)
*/
#define HT_CONFIG_PORT 0x3e6
#define HT_CONFIG(drivea) (byte)(((drivea)->drive_data & 0xff00) >> 8)
#define HT_CONFIG(drivea) (u8)(((drivea)->drive_data & 0xff00) >> 8)
/*
* FIFO + PREFETCH (both a/b-model)
*/
......@@ -114,7 +122,7 @@
* Active Time for each drive. Smaller value gives higher speed.
* In case of failures you should probably fall back to a higher value.
*/
#define HT_TIMING(drivea) (byte)((drivea)->drive_data & 0x00ff)
#define HT_TIMING(drivea) (u8)((drivea)->drive_data & 0x00ff)
#define HT_TIMING_DEFAULT 0xff
/*
......@@ -130,9 +138,9 @@
static void ht6560b_selectproc (ide_drive_t *drive)
{
unsigned long flags;
static byte current_select = 0;
static byte current_timing = 0;
byte select, timing;
static u8 current_select = 0;
static u8 current_timing = 0;
u8 select, timing;
local_irq_save(flags);
......@@ -144,16 +152,16 @@ static void ht6560b_selectproc (ide_drive_t *drive)
current_timing = timing;
if (drive->media != ide_disk || !drive->present)
select |= HT_PREFETCH_MODE;
(void) IN_BYTE(HT_CONFIG_PORT);
(void) IN_BYTE(HT_CONFIG_PORT);
(void) IN_BYTE(HT_CONFIG_PORT);
(void) IN_BYTE(HT_CONFIG_PORT);
OUT_BYTE(select, HT_CONFIG_PORT);
(void) HWIF(drive)->INB(HT_CONFIG_PORT);
(void) HWIF(drive)->INB(HT_CONFIG_PORT);
(void) HWIF(drive)->INB(HT_CONFIG_PORT);
(void) HWIF(drive)->INB(HT_CONFIG_PORT);
HWIF(drive)->OUTB(select, HT_CONFIG_PORT);
/*
* Set timing for this drive:
*/
OUT_BYTE(timing, IDE_SELECT_REG);
(void) IN_BYTE(IDE_STATUS_REG);
HWIF(drive)->OUTB(timing, IDE_SELECT_REG);
(void) HWIF(drive)->INB(IDE_STATUS_REG);
#ifdef DEBUG
printk("ht6560b: %s: select=%#x timing=%#x\n",
drive->name, select, timing);
......@@ -167,31 +175,31 @@ static void ht6560b_selectproc (ide_drive_t *drive)
*/
static int __init try_to_init_ht6560b(void)
{
byte orig_value;
u8 orig_value;
int i;
/* Autodetect ht6560b */
if ((orig_value = IN_BYTE(HT_CONFIG_PORT)) == 0xff)
if ((orig_value = inb(HT_CONFIG_PORT)) == 0xff)
return 0;
for (i=3;i>0;i--) {
OUT_BYTE(0x00, HT_CONFIG_PORT);
if (!( (~IN_BYTE(HT_CONFIG_PORT)) & 0x3f )) {
OUT_BYTE(orig_value, HT_CONFIG_PORT);
outb(0x00, HT_CONFIG_PORT);
if (!( (~inb(HT_CONFIG_PORT)) & 0x3f )) {
outb(orig_value, HT_CONFIG_PORT);
return 0;
}
}
OUT_BYTE(0x00, HT_CONFIG_PORT);
if ((~IN_BYTE(HT_CONFIG_PORT))& 0x3f) {
OUT_BYTE(orig_value, HT_CONFIG_PORT);
outb(0x00, HT_CONFIG_PORT);
if ((~inb(HT_CONFIG_PORT))& 0x3f) {
outb(orig_value, HT_CONFIG_PORT);
return 0;
}
/*
* Ht6560b autodetected
*/
OUT_BYTE(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
OUT_BYTE(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */
(void) IN_BYTE(0x1f7); /* IDE_STATUS_REG */
outb(HT_CONFIG_DEFAULT, HT_CONFIG_PORT);
outb(HT_TIMING_DEFAULT, 0x1f6); /* IDE_SELECT_REG */
(void) inb(0x1f7); /* IDE_STATUS_REG */
printk("\nht6560b " HT6560B_VERSION
": chipset detected and initialized"
......@@ -202,7 +210,7 @@ static int __init try_to_init_ht6560b(void)
return 1;
}
static byte ht_pio2timings(ide_drive_t *drive, byte pio)
static u8 ht_pio2timings(ide_drive_t *drive, u8 pio)
{
int active_time, recovery_time;
int active_cycles, recovery_cycles;
......@@ -238,7 +246,7 @@ static byte ht_pio2timings(ide_drive_t *drive, byte pio)
printk("ht6560b: drive %s setting pio=%d recovery=%d (%dns) active=%d (%dns)\n", drive->name, pio, recovery_cycles, recovery_time, active_cycles, active_time);
#endif
return (byte)((recovery_cycles << 4) | active_cycles);
return (u8)((recovery_cycles << 4) | active_cycles);
} else {
#ifdef DEBUG
......@@ -252,7 +260,7 @@ static byte ht_pio2timings(ide_drive_t *drive, byte pio)
/*
* Enable/Disable so called prefetch mode
*/
static void ht_set_prefetch(ide_drive_t *drive, byte state)
static void ht_set_prefetch(ide_drive_t *drive, u8 state)
{
unsigned long flags;
int t = HT_PREFETCH_MODE << 8;
......@@ -278,10 +286,10 @@ static void ht_set_prefetch(ide_drive_t *drive, byte state)
#endif
}
static void tune_ht6560b (ide_drive_t *drive, byte pio)
static void tune_ht6560b (ide_drive_t *drive, u8 pio)
{
unsigned long flags;
byte timing;
u8 timing;
switch (pio) {
case 8: /* set prefetch off */
......@@ -304,14 +312,10 @@ static void tune_ht6560b (ide_drive_t *drive, byte pio)
#endif
}
void __init init_ht6560b (void)
void __init probe_ht6560b (void)
{
int t;
if (check_region(HT_CONFIG_PORT,1)) {
printk(KERN_ERR "ht6560b: PORT %#x ALREADY IN USE\n", HT_CONFIG_PORT);
} else {
if (try_to_init_ht6560b()) {
request_region(HT_CONFIG_PORT, 1, ide_hwifs[0].name);
ide_hwifs[0].chipset = ide_ht6560b;
ide_hwifs[1].chipset = ide_ht6560b;
......@@ -335,7 +339,92 @@ void __init init_ht6560b (void)
t |= (HT_SECONDARY_IF << 8);
ide_hwifs[1].drives[0].drive_data = t;
ide_hwifs[1].drives[1].drive_data = t;
} else
printk(KERN_ERR "ht6560b: not found\n");
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init(&ide_hwifs[0]);
probe_hwif_init(&ide_hwifs[1]);
#endif /* HWIF_PROBE_CLASSIC_METHOD */
}
void __init ht6560b_release (void)
{
if (ide_hwifs[0].chipset != ide_ht6560b &&
ide_hwifs[1].chipset != ide_ht6560b)
return;
ide_hwifs[0].chipset = ide_unknown;
ide_hwifs[1].chipset = ide_unknown;
ide_hwifs[0].tuneproc = NULL;
ide_hwifs[1].tuneproc = NULL;
ide_hwifs[0].selectproc = NULL;
ide_hwifs[1].selectproc = NULL;
ide_hwifs[0].serialized = 0;
ide_hwifs[1].serialized = 0;
ide_hwifs[0].mate = NULL;
ide_hwifs[1].mate = NULL;
ide_hwifs[0].drives[0].drive_data = 0;
ide_hwifs[0].drives[1].drive_data = 0;
ide_hwifs[1].drives[0].drive_data = 0;
ide_hwifs[1].drives[1].drive_data = 0;
release_region(HT_CONFIG_PORT, 1);
}
#ifndef MODULE
/*
* init_ht6560b:
*
* called by ide.c when parsing command line
*/
void __init init_ht6560b (void)
{
if (check_region(HT_CONFIG_PORT,1)) {
printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
__FUNCTION__);
return;
}
if (!try_to_init_ht6560b()) {
printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__);
return;
}
probe_ht6560b();
}
#else
MODULE_AUTHOR("See Local File");
MODULE_DESCRIPTION("HT-6560B EIDE-controller support");
MODULE_LICENSE("GPL");
int __init ht6560b_mod_init(void)
{
if (check_region(HT_CONFIG_PORT,1)) {
printk(KERN_NOTICE "%s: HT_CONFIG_PORT not found\n",
__FUNCTION__);
return -ENODEV;
}
if (!try_to_init_ht6560b()) {
printk(KERN_NOTICE "%s: HBA not found\n", __FUNCTION__);
return -ENODEV;
}
probe_ht6560b();
if (ide_hwifs[0].chipset != ide_ht6560b &&
ide_hwifs[1].chipset != ide_ht6560b) {
ht6560b_release();
return -ENODEV;
}
return 0;
}
module_init(ht6560b_mod_init);
void __init ht6560b_mod_exit(void)
{
ht6560b_release();
}
module_exit(ht6560b_mod_exit);
#endif
......@@ -340,12 +340,12 @@ void ide_config(dev_link_t *link)
/* retry registration in case device is still spinning up */
for (i = 0; i < 10; i++) {
if (ctl_base)
OUT_BYTE(0x02, ctl_base); /* Set nIEN = disable device interrupts */
outb(0x02, ctl_base); /* Set nIEN = disable device interrupts */
hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ);
if (hd >= 0) break;
if (link->io.NumPorts1 == 0x20) {
if (ctl_base)
OUT_BYTE(0x02, ctl_base+0x10);
outb(0x02, ctl_base+0x10);
hd = idecs_register(io_base+0x10, ctl_base+0x10,
link->irq.AssignedIRQ);
if (hd >= 0) {
......
......@@ -83,7 +83,7 @@ static void macide_mediabay_interrupt(int irq, void *dev_id, struct pt_regs *reg
{
int state = baboon->mb_status & 0x04;
printk("macide: media bay %s detected\n", state? "removal":"insertion");
printk(KERN_INFO "macide: media bay %s detected\n", state? "removal":"insertion");
}
#endif
......@@ -99,24 +99,30 @@ void macide_init(void)
switch (macintosh_config->ide_type) {
case MAC_IDE_QUADRA:
ide_setup_ports(&hw, (ide_ioreg_t)IDE_BASE, macide_offsets,
0, 0, macide_ack_intr, IRQ_NUBUS_F);
0, 0, macide_ack_intr,
// quadra_ide_iops,
IRQ_NUBUS_F);
index = ide_register_hw(&hw, NULL);
break;
case MAC_IDE_PB:
ide_setup_ports(&hw, (ide_ioreg_t)IDE_BASE, macide_offsets,
0, 0, macide_ack_intr, IRQ_NUBUS_C);
0, 0, macide_ack_intr,
// macide_pb_iops,
IRQ_NUBUS_C);
index = ide_register_hw(&hw, NULL);
break;
case MAC_IDE_BABOON:
ide_setup_ports(&hw, (ide_ioreg_t)BABOON_BASE, macide_offsets,
0, 0, NULL, IRQ_BABOON_1);
0, 0, NULL,
// macide_baboon_iops,
IRQ_BABOON_1);
index = ide_register_hw(&hw, NULL);
if (index == -1) break;
if (macintosh_config->ident == MAC_MODEL_PB190) {
/* Fix breakage in ide-disk.c: drive capacity */
/* is not initialized for drives without a */
/* hardware ID, and we cna't get that without */
/* hardware ID, and we can't get that without */
/* probing the drive which freezes a 190. */
ide_drive_t *drive = &ide_hwifs[index].drives[0];
......@@ -136,12 +142,12 @@ void macide_init(void)
if (index != -1) {
if (macintosh_config->ide_type == MAC_IDE_QUADRA)
printk("ide%d: Macintosh Quadra IDE interface\n", index);
printk(KERN_INFO "ide%d: Macintosh Quadra IDE interface\n", index);
else if (macintosh_config->ide_type == MAC_IDE_PB)
printk("ide%d: Macintosh Powerbook IDE interface\n", index);
printk(KERN_INFO "ide%d: Macintosh Powerbook IDE interface\n", index);
else if (macintosh_config->ide_type == MAC_IDE_BABOON)
printk("ide%d: Macintosh Powerbook Baboon IDE interface\n", index);
printk(KERN_INFO "ide%d: Macintosh Powerbook Baboon IDE interface\n", index);
else
printk("ide%d: Unknown Macintosh IDE interface\n", index);
printk(KERN_INFO "ide%d: Unknown Macintosh IDE interface\n", index);
}
}
/* -*- linux-c -*-
* linux/drivers/ide/pdc4030.c Version 0.90 May 27, 1999
*
* Copyright (C) 1995-1999 Linus Torvalds & authors (see below)
* Copyright (C) 1995-2002 Linus Torvalds & authors (see below)
*/
/*
* Principal Author/Maintainer: peterd@pnd-pc.demon.co.uk
* Principal Author/Maintainer: Peter Denison <promise@pnd-pc.demon.co.uk>
*
* This file provides support for the second port and cache of Promise
* IDE interfaces, e.g. DC4030VL, DC4030VL-1 and DC4030VL-2.
......@@ -66,13 +66,18 @@
* some technical information which has shed a glimmer of light on some of the
* problems I was having, especially with writes.
*
* There are still problems with the robustness and efficiency of this driver
* because I still don't understand what the card is doing with interrupts.
* There are still potential problems with the robustness and efficiency of
* this driver because I still don't understand what the card is doing with
* interrupts, however, it has been stable for a while with no reports of ill
* effects.
*/
#define DEBUG_READ
#define DEBUG_WRITE
#define __PROMISE_4030
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
......@@ -98,7 +103,7 @@ static void promise_selectproc (ide_drive_t *drive)
unsigned int number;
number = (HWIF(drive)->channel << 1) + drive->select.b.unit;
OUT_BYTE(number,IDE_FEATURE_REG);
HWIF(drive)->OUTB(number, IDE_FEATURE_REG);
}
/*
......@@ -106,26 +111,24 @@ static void promise_selectproc (ide_drive_t *drive)
* by command F0. They all have the same success/failure notification -
* 'P' (=0x50) on success, 'p' (=0x70) on failure.
*/
int pdc4030_cmd(ide_drive_t *drive, byte cmd)
int pdc4030_cmd(ide_drive_t *drive, u8 cmd)
{
unsigned long timeout, timer;
byte status_val;
u32 timeout;
u8 status_val;
promise_selectproc(drive); /* redundant? */
OUT_BYTE(0xF3,IDE_SECTOR_REG);
OUT_BYTE(cmd,IDE_SELECT_REG);
OUT_BYTE(PROMISE_EXTENDED_COMMAND,IDE_COMMAND_REG);
HWIF(drive)->OUTB(0xF3, IDE_SECTOR_REG);
HWIF(drive)->OUTB(cmd, IDE_SELECT_REG);
HWIF(drive)->OUTB(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG);
timeout = HZ * 10;
timeout += jiffies;
do {
if(time_after(jiffies, timeout)) {
return 2; /* device timed out */
}
/* This is out of delay_10ms() */
/* Delays at least 10ms to give interface a chance */
timer = jiffies + (HZ + 99)/100 + 1;
while (time_after(timer, jiffies));
status_val = IN_BYTE(IDE_SECTOR_REG);
mdelay(10);
status_val = HWIF(drive)->INB(IDE_SECTOR_REG);
} while (status_val != 0x50 && status_val != 0x70);
if(status_val == 0x50)
......@@ -142,18 +145,13 @@ int pdc4030_identify(ide_drive_t *drive)
return pdc4030_cmd(drive, PROMISE_IDENTIFY);
}
int enable_promise_support = 0;
void __init init_pdc4030 (void)
{
enable_promise_support = 1;
}
int enable_promise_support;
/*
* setup_pdc4030()
* Completes the setup of a Promise DC4030 controller card, once found.
*/
int __init setup_pdc4030 (ide_hwif_t *hwif)
int __init setup_pdc4030(ide_hwif_t *hwif)
{
ide_drive_t *drive;
ide_hwif_t *hwif2;
......@@ -168,12 +166,12 @@ int __init setup_pdc4030 (ide_hwif_t *hwif)
if (hwif->chipset == ide_pdc4030) /* we've already been found ! */
return 1;
if (IN_BYTE(IDE_NSECTOR_REG) == 0xFF ||
IN_BYTE(IDE_SECTOR_REG) == 0xFF) {
if (hwif->INB(IDE_NSECTOR_REG) == 0xFF ||
hwif->INB(IDE_SECTOR_REG) == 0xFF) {
return 0;
}
if (IDE_CONTROL_REG)
OUT_BYTE(0x08,IDE_CONTROL_REG);
hwif->OUTB(0x08, IDE_CONTROL_REG);
if (pdc4030_cmd(drive,PROMISE_GET_CONFIG)) {
return 0;
}
......@@ -182,7 +180,7 @@ int __init setup_pdc4030 (ide_hwif_t *hwif)
"%s: Failed Promise read config!\n",hwif->name);
return 0;
}
ata_input_data(drive, &ident, SECTOR_WORDS);
hwif->ata_input_data(drive, &ident, SECTOR_WORDS);
if (ident.id[1] != 'P' || ident.id[0] != 'T') {
return 0;
}
......@@ -226,15 +224,19 @@ int __init setup_pdc4030 (ide_hwif_t *hwif)
hwif->mate = hwif2;
hwif2->mate = hwif;
hwif2->channel = 1;
hwif->rqsize = hwif2->rqsize = 127;
hwif->addressing = hwif2->addressing = 1;
hwif->selectproc = hwif2->selectproc = &promise_selectproc;
hwif->serialized = hwif2->serialized = 1;
/* DC4030 hosted drives need their own identify... */
hwif->identify = hwif2->identify = &pdc4030_identify;
/* Shift the remaining interfaces down by one */
/* Shift the remaining interfaces up by one */
for (i=MAX_HWIFS-1 ; i > hwif->index+1 ; i--) {
ide_hwif_t *h = &ide_hwifs[i];
#ifdef DEBUG
printk(KERN_DEBUG "Shifting i/f %d values to i/f %d\n",i-1,i);
printk(KERN_DEBUG "pdc4030: Shifting i/f %d values to i/f %d\n",i-1,i);
#endif /* DEBUG */
ide_init_hwif_ports(&h->hw, (h-1)->io_ports[IDE_DATA_OFFSET], 0, NULL);
memcpy(h->io_ports, h->hw.io_ports, sizeof(h->io_ports));
......@@ -254,6 +256,11 @@ int __init setup_pdc4030 (ide_hwif_t *hwif)
if (!ident.current_tm[i+2].cyl)
hwif2->drives[i].noprobe = 1;
}
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init(&ide_hwifs[hwif->index]);
probe_hwif_init(&ide_hwifs[hwif2->index]);
#endif /* HWIF_PROBE_CLASSIC_METHOD */
return 1;
}
......@@ -269,58 +276,152 @@ int __init detect_pdc4030(ide_hwif_t *hwif)
if (IDE_DATA_REG == 0) { /* Skip test for non-existent interface */
return 0;
}
OUT_BYTE(0xF3, IDE_SECTOR_REG);
OUT_BYTE(0x14, IDE_SELECT_REG);
OUT_BYTE(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG);
hwif->OUTB(0xF3, IDE_SECTOR_REG);
hwif->OUTB(0x14, IDE_SELECT_REG);
hwif->OUTB(PROMISE_EXTENDED_COMMAND, IDE_COMMAND_REG);
ide_delay_50ms();
if (IN_BYTE(IDE_ERROR_REG) == 'P' &&
IN_BYTE(IDE_NSECTOR_REG) == 'T' &&
IN_BYTE(IDE_SECTOR_REG) == 'I') {
if (hwif->INB(IDE_ERROR_REG) == 'P' &&
hwif->INB(IDE_NSECTOR_REG) == 'T' &&
hwif->INB(IDE_SECTOR_REG) == 'I') {
return 1;
} else {
return 0;
}
}
#ifndef MODULE
void __init ide_probe_for_pdc4030(void)
#else
int ide_probe_for_pdc4030(void)
#endif
{
unsigned int index;
ide_hwif_t *hwif;
#ifndef MODULE
if (enable_promise_support == 0)
return;
#endif
for (index = 0; index < MAX_HWIFS; index++) {
hwif = &ide_hwifs[index];
if (hwif->chipset == ide_unknown && detect_pdc4030(hwif)) {
#ifndef MODULE
setup_pdc4030(hwif);
#else
return setup_pdc4030(hwif);
#endif
}
}
#ifdef MODULE
return 0;
#endif
}
void __init release_pdc4030(ide_hwif_t *hwif, ide_hwif_t *mate)
{
hwif->chipset = ide_unknown;
hwif->selectproc = NULL;
hwif->serialized = 0;
hwif->drives[0].io_32bit = 0;
hwif->drives[1].io_32bit = 0;
hwif->drives[0].keep_settings = 0;
hwif->drives[1].keep_settings = 0;
hwif->drives[0].noprobe = 0;
hwif->drives[1].noprobe = 0;
if (mate != NULL) {
mate->chipset = ide_unknown;
mate->selectproc = NULL;
mate->serialized = 0;
mate->drives[0].io_32bit = 0;
mate->drives[1].io_32bit = 0;
mate->drives[0].keep_settings = 0;
mate->drives[1].keep_settings = 0;
mate->drives[0].noprobe = 0;
mate->drives[1].noprobe = 0;
}
}
#ifndef MODULE
/*
* init_pdc4030:
*
* called by ide.c when parsing command line
*/
void __init init_pdc4030(void)
{
enable_promise_support = 1;
}
#else
MODULE_AUTHOR("Peter Denison");
MODULE_DESCRIPTION("Support of Promise 4030 VLB series IDE chipsets");
MODULE_LICENSE("GPL");
int __init pdc4030_mod_init(void)
{
if (enable_promise_support == 0)
enable_promise_support = 1;
if (!ide_probe_for_pdc4030())
return -ENODEV;
return 0;
}
module_init(pdc4030_mod_init);
void __init pdc4030_mod_exit(void)
{
unsigned int index;
ide_hwif_t *hwif;
if (enable_promise_support == 0)
return;
for (index = 0; index < MAX_HWIFS; index++) {
hwif = &ide_hwifs[index];
if (hwif->chipset == ide_pdc4030) {
ide_hwif_t *mate = &ide_hwifs[hwif->index+1];
if (mate->chipset == ide_pdc4030)
release_pdc4030(hwif, mate);
else
release_pdc4030(hwif, NULL);
}
}
enable_promise_support = 0;
}
module_exit(pdc4030_mod_exit);
#endif
/*
* promise_read_intr() is the handler for disk read/multread interrupts
*/
static ide_startstop_t promise_read_intr (ide_drive_t *drive)
{
byte stat;
int total_remaining;
unsigned int sectors_left, sectors_avail, nsect;
struct request *rq;
ata_status_t status;
#ifdef CONFIG_IDE_TASKFILE_IO
unsigned long flags;
char *to;
#endif /* CONFIG_IDE_TASKFILE_IO */
if (!OK_STAT(stat=GET_STAT(),DATA_READY,BAD_R_STAT))
return DRIVER(drive)->error(drive, "promise_read_intr", stat);
status.all = HWIF(drive)->INB(IDE_STATUS_REG);
if (!OK_STAT(status.all, DATA_READY, BAD_R_STAT))
return DRIVER(drive)->error(drive,
"promise_read_intr", status.all);
read_again:
do {
sectors_left = IN_BYTE(IDE_NSECTOR_REG);
IN_BYTE(IDE_SECTOR_REG);
} while (IN_BYTE(IDE_NSECTOR_REG) != sectors_left);
sectors_left = HWIF(drive)->INB(IDE_NSECTOR_REG);
HWIF(drive)->INB(IDE_SECTOR_REG);
} while (HWIF(drive)->INB(IDE_NSECTOR_REG) != sectors_left);
rq = HWGROUP(drive)->rq;
sectors_avail = rq->nr_sectors - sectors_left;
if (!sectors_avail)
......@@ -334,9 +435,9 @@ static ide_startstop_t promise_read_intr (ide_drive_t *drive)
sectors_avail -= nsect;
#ifdef CONFIG_IDE_TASKFILE_IO
to = ide_map_buffer(rq, &flags);
ata_input_data(drive, to, nsect * SECTOR_WORDS);
HWIF(drive)->ata_input_data(drive, to, nsect * SECTOR_WORDS);
#else /* !CONFIG_IDE_TASKFILE_IO */
ata_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
HWIF(drive)->ata_input_data(drive, rq->buffer, nsect * SECTOR_WORDS);
#endif /* CONFIG_IDE_TASKFILE_IO */
#ifdef DEBUG_READ
......@@ -377,13 +478,16 @@ static ide_startstop_t promise_read_intr (ide_drive_t *drive)
if (total_remaining > 0) {
if (sectors_avail)
goto read_next;
stat = GET_STAT();
if (stat & DRQ_STAT)
status.all = HWIF(drive)->INB(IDE_STATUS_REG);
if (status.b.drq)
goto read_again;
if (stat & BUSY_STAT) {
if (HWGROUP(drive)->handler != NULL) /* paranoia check */
if (status.b.bsy) {
if (HWGROUP(drive)->handler != NULL)
BUG();
ide_set_handler (drive, &promise_read_intr, WAIT_CMD, NULL);
ide_set_handler(drive,
&promise_read_intr,
WAIT_CMD,
NULL);
#ifdef DEBUG_READ
printk(KERN_DEBUG "%s: promise_read: waiting for"
"interrupt\n", drive->name);
......@@ -392,7 +496,8 @@ static ide_startstop_t promise_read_intr (ide_drive_t *drive)
}
printk(KERN_ERR "%s: Eeek! promise_read_intr: sectors left "
"!DRQ !BUSY\n", drive->name);
return DRIVER(drive)->error(drive, "promise read intr", stat);
return DRIVER(drive)->error(drive,
"promise read intr", status.all);
}
return ide_stopped;
}
......@@ -411,17 +516,21 @@ static ide_startstop_t promise_complete_pollfunc(ide_drive_t *drive)
struct request *rq = hwgroup->rq;
int i;
if (GET_STAT() & BUSY_STAT) {
if ((HWIF(drive)->INB(IDE_STATUS_REG)) & BUSY_STAT) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
if (HWGROUP(drive)->handler != NULL) /* paranoia check */
if (hwgroup->handler != NULL)
BUG();
ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
ide_set_handler(drive,
&promise_complete_pollfunc,
HZ/100,
NULL);
return ide_started; /* continue polling... */
}
hwgroup->poll_timeout = 0;
printk(KERN_ERR "%s: completion timeout - still busy!\n",
drive->name);
return DRIVER(drive)->error(drive, "busy timeout", GET_STAT());
return DRIVER(drive)->error(drive, "busy timeout",
HWIF(drive)->INB(IDE_STATUS_REG));
}
hwgroup->poll_timeout = 0;
......@@ -475,24 +584,16 @@ int promise_multwrite (ide_drive_t *drive, unsigned int mcount)
/* Do we move to the next bh after this? */
if (!rq->current_nr_sectors) {
struct bio *bio = rq->bio;
/*
* only move to next bio, when we have processed
* all bvecs in this one.
*/
if (++bio->bi_idx >= bio->bi_vcnt) {
bio->bi_idx = 0;
bio = bio->bi_next;
}
struct buffer_head *bh = rq->bh->b_reqnext;
/* end early early we ran out of requests */
if (!bio) {
if (!bh) {
mcount = 0;
} else {
rq->bio = bio;
rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
rq->bh = bh;
rq->current_nr_sectors = bh->b_size >> 9;
rq->hard_cur_sectors = rq->current_nr_sectors;
rq->buffer = bh->b_data;
}
}
......@@ -516,16 +617,20 @@ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
if (HWIF(drive)->INB(IDE_NSECTOR_REG) != 0) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
if (HWGROUP(drive)->handler != NULL) /* paranoia check */
if (hwgroup->handler != NULL)
BUG();
ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);
ide_set_handler(drive,
&promise_write_pollfunc,
HZ/100,
NULL);
return ide_started; /* continue polling... */
}
hwgroup->poll_timeout = 0;
printk(KERN_ERR "%s: write timed-out!\n",drive->name);
return DRIVER(drive)->error(drive, "write timeout", GET_STAT());
return DRIVER(drive)->error(drive, "write timeout",
HWIF(drive)->INB(IDE_STATUS_REG));
}
/*
......@@ -533,12 +638,12 @@ static ide_startstop_t promise_write_pollfunc (ide_drive_t *drive)
*/
promise_multwrite(drive, 4);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
if (HWGROUP(drive)->handler != NULL) /* paranoia check */
if (hwgroup->handler != NULL)
BUG();
ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
drive->name, GET_STAT());
drive->name, HWIF(drive)->INB(IDE_STATUS_REG));
#endif /* DEBUG_WRITE */
return ide_started;
}
......@@ -569,7 +674,7 @@ static ide_startstop_t promise_write (ide_drive_t *drive)
if (promise_multwrite(drive, rq->nr_sectors - 4))
return ide_stopped;
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
if (HWGROUP(drive)->handler != NULL) /* paranoia check */
if (hwgroup->handler != NULL) /* paranoia check */
BUG();
ide_set_handler (drive, &promise_write_pollfunc, HZ/100, NULL);
return ide_started;
......@@ -581,19 +686,24 @@ static ide_startstop_t promise_write (ide_drive_t *drive)
if (promise_multwrite(drive, rq->nr_sectors))
return ide_stopped;
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
if (HWGROUP(drive)->handler != NULL) /* paranoia check */
if (hwgroup->handler != NULL)
BUG();
ide_set_handler(drive, &promise_complete_pollfunc, HZ/100, NULL);
ide_set_handler(drive,
&promise_complete_pollfunc,
HZ/100,
NULL);
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
"status = %02x\n", drive->name, GET_STAT());
"status = %02x\n", drive->name,
HWIF(drive)->INB(IDE_STATUS_REG));
#endif /* DEBUG_WRITE */
return ide_started;
}
}
/*
* do_pdc4030_io() is called from do_rw_disk, having had the block number
* do_pdc4030_io() is called from promise_rw_disk, having had the block number
* already set up. It issues a READ or WRITE command to the Promise
* controller, assuming LBA has been used to set up the block number.
*/
......@@ -608,29 +718,27 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
#endif /* CONFIG_IDE_TASKFILE_IO */
ide_startstop_t startstop;
unsigned long timeout;
byte stat;
BUG_ON(!(rq->flags & REQ_CMD));
u8 stat = 0;
#ifdef CONFIG_IDE_TASKFILE_IO
if (IDE_CONTROL_REG)
OUT_BYTE(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
SELECT_MASK(HWIF(drive), drive, 0);
OUT_BYTE(taskfile->feature, IDE_FEATURE_REG);
OUT_BYTE(taskfile->sector_count, IDE_NSECTOR_REG);
HWIF(drive)->OUTB(drive->ctl, IDE_CONTROL_REG); /* clear nIEN */
SELECT_MASK(drive, 0);
HWIF(drive)->OUTB(taskfile->feature, IDE_FEATURE_REG);
HWIF(drive)->OUTB(taskfile->sector_count, IDE_NSECTOR_REG);
/* refers to number of sectors to transfer */
OUT_BYTE(taskfile->sector_number, IDE_SECTOR_REG);
HWIF(drive)->OUTB(taskfile->sector_number, IDE_SECTOR_REG);
/* refers to sector offset or start sector */
OUT_BYTE(taskfile->low_cylinder, IDE_LCYL_REG);
OUT_BYTE(taskfile->high_cylinder, IDE_HCYL_REG);
OUT_BYTE(taskfile->device_head, IDE_SELECT_REG);
OUT_BYTE(taskfile->command, IDE_COMMAND_REG);
HWIF(drive)->OUTB(taskfile->low_cylinder, IDE_LCYL_REG);
HWIF(drive)->OUTB(taskfile->high_cylinder, IDE_HCYL_REG);
HWIF(drive)->OUTB(taskfile->device_head, IDE_SELECT_REG);
HWIF(drive)->OUTB(taskfile->command, IDE_COMMAND_REG);
#endif /* CONFIG_IDE_TASKFILE_IO */
if (rq_data_dir(rq) == READ) {
switch(rq->cmd) {
case READ:
#ifndef CONFIG_IDE_TASKFILE_IO
OUT_BYTE(PROMISE_READ, IDE_COMMAND_REG);
HWIF(drive)->OUTB(PROMISE_READ, IDE_COMMAND_REG);
#endif /* CONFIG_IDE_TASKFILE_IO */
/*
* The card's behaviour is odd at this point. If the data is
......@@ -644,17 +752,20 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
*/
timeout = jiffies + HZ/20; /* 50ms wait */
do {
stat=GET_STAT();
stat = HWIF(drive)->INB(IDE_STATUS_REG);
if (stat & DRQ_STAT) {
udelay(1);
return promise_read_intr(drive);
}
if (IN_BYTE(IDE_SELECT_REG) & 0x01) {
if (HWIF(drive)->INB(IDE_SELECT_REG) & 0x01) {
#ifdef DEBUG_READ
printk(KERN_DEBUG "%s: read: waiting for "
"interrupt\n", drive->name);
#endif /* DEBUG_READ */
ide_set_handler(drive, &promise_read_intr, WAIT_CMD, NULL);
ide_set_handler(drive,
&promise_read_intr,
WAIT_CMD,
NULL);
return ide_started;
}
udelay(1);
......@@ -663,9 +774,9 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
printk(KERN_ERR "%s: reading: No DRQ and not "
"waiting - Odd!\n", drive->name);
return ide_stopped;
} else if (rq_data_dir(rq) == WRITE) {
case WRITE:
#ifndef CONFIG_IDE_TASKFILE_IO
OUT_BYTE(PROMISE_WRITE, IDE_COMMAND_REG);
HWIF(drive)->OUTB(PROMISE_WRITE, IDE_COMMAND_REG);
#endif /* CONFIG_IDE_TASKFILE_IO */
if (ide_wait_stat(&startstop, drive, DATA_READY,
drive->bad_wstat, WAIT_DRQ)) {
......@@ -677,22 +788,53 @@ ide_startstop_t do_pdc4030_io (ide_drive_t *drive, ide_task_t *task)
local_irq_disable();
HWGROUP(drive)->wrq = *rq; /* scratchpad */
return promise_write(drive);
} else {
blk_dump_rq_flags(rq, "do_pdc4030_io - bad command\n");
default:
printk("KERN_WARNING %s: bad command: %d\n",
drive->name, rq->cmd);
DRIVER(drive)->end_request(drive, 0);
return ide_stopped;
}
}
#ifdef CONFIG_IDE_TASKFILE_IO
ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigned long block)
{
/* The four drives on the two logical (one physical) interfaces
are distinguished by writing the drive number (0-3) to the
Feature register.
FIXME: Is promise_selectproc now redundant??
*/
int drive_number = (HWIF(drive)->channel << 1) + drive->select.b.unit;
#ifndef CONFIG_IDE_TASKFILE_IO
ide_hwif_t *hwif = HWIF(drive);
BUG_ON(rq->nr_sectors > 127);
if (IDE_CONTROL_REG)
hwif->OUTB(drive->ctl, IDE_CONTROL_REG);
#ifdef DEBUG
printk("%s: %sing: LBAsect=%ld, sectors=%ld, "
"buffer=0x%08lx\n", drive->name,
(rq->cmd==READ)?"read":"writ", block,
rq->nr_sectors, (unsigned long) rq->buffer);
#endif
hwif->OUTB(drive_number, IDE_FEATURE_REG);
hwif->OUTB(rq->nr_sectors, IDE_NSECTOR_REG);
hwif->OUTB(block,IDE_SECTOR_REG);
hwif->OUTB(block>>=8,IDE_LCYL_REG);
hwif->OUTB(block>>=8,IDE_HCYL_REG);
hwif->OUTB(((block>>8)&0x0f)|drive->select.all,IDE_SELECT_REG);
return do_pdc4030_io(drive, rq);
#else /* CONFIG_IDE_TASKFILE_IO */
struct hd_drive_task_hdr taskfile;
ide_task_t args;
memset(&taskfile, 0, sizeof(struct hd_drive_task_hdr));
taskfile.feature = drive_number;
taskfile.sector_count = rq->nr_sectors;
taskfile.sector_number = block;
taskfile.low_cylinder = (block>>=8);
......@@ -701,16 +843,16 @@ ide_startstop_t promise_rw_disk (ide_drive_t *drive, struct request *rq, unsigne
taskfile.command = (rq->cmd==READ)?PROMISE_READ:PROMISE_WRITE;
memcpy(args.tfRegister, &taskfile, sizeof(struct hd_drive_task_hdr));
memcpy(args.hobRegister, NULL, sizeof(struct hd_drive_hob_hdr));
args.command_type = ide_cmd_type_parser(&args);
args.prehandler = NULL;
memset(args.hobRegister, 0, sizeof(struct hd_drive_hob_hdr));
/* We can't call ide_cmd_type_parser here, since it won't understand
our command, but that doesn't matter, since we don't use the
generic interrupt handlers either. Setup the bits of args that we
do need.
*/
args.handler = NULL;
args.posthandler = NULL;
args.rq = (struct request *) rq;
rq->special = NULL;
rq->special = (ide_task_t *)&args;
return do_pdc4030_io(drive, &args);
}
#endif /* CONFIG_IDE_TASKFILE_IO */
}
......@@ -84,7 +84,9 @@ void q40ide_init(void)
ide_setup_ports(&hw,(ide_ioreg_t) pcide_bases[i], (int *)pcide_offsets,
pcide_bases[i]+0x206,
0, NULL, q40ide_default_irq(pcide_bases[i]));
0, NULL,
// pcide_iops,
q40ide_default_irq(pcide_bases[i]));
ide_register_hw(&hw, NULL);
}
}
......
......@@ -27,6 +27,8 @@
#undef REALLY_SLOW_IO /* most systems can safely undef this */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
......@@ -37,9 +39,17 @@
#include <linux/hdreg.h>
#include <linux/ide.h>
#include <linux/init.h>
#include <asm/system.h>
#include <asm/io.h>
#include "ide_modes.h"
#ifdef CONFIG_BLK_DEV_QD65XX_MODULE
# define _IDE_C
# include "ide_modes.h"
# undef _IDE_C
#else
# include "ide_modes.h"
#endif /* CONFIG_BLK_DEV_QD65XX_MODULE */
#include "qd65xx.h"
/*
......@@ -90,22 +100,22 @@
static int timings[4]={-1,-1,-1,-1}; /* stores current timing for each timer */
static void qd_write_reg (byte content, byte reg)
static void qd_write_reg (u8 content, u8 reg)
{
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
OUT_BYTE(content,reg);
outb(content,reg);
spin_unlock_irqrestore(&ide_lock, flags);
}
byte __init qd_read_reg (byte reg)
u8 __init qd_read_reg (u8 reg)
{
unsigned long flags;
byte read;
u8 read;
spin_lock_irqsave(&ide_lock, flags);
read = IN_BYTE(reg);
read = inb(reg);
spin_unlock_irqrestore(&ide_lock, flags);
return read;
}
......@@ -118,7 +128,7 @@ byte __init qd_read_reg (byte reg)
static void qd_select (ide_drive_t *drive)
{
byte index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) |
u8 index = (( (QD_TIMREG(drive)) & 0x80 ) >> 7) |
(QD_TIMREG(drive) & 0x02);
if (timings[index] != QD_TIMING(drive))
......@@ -133,16 +143,16 @@ static void qd_select (ide_drive_t *drive)
* upper nibble represents recovery time, in count of VLB clocks
*/
static byte qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
static u8 qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recovery_time)
{
byte active_cycle,recovery_cycle;
u8 active_cycle,recovery_cycle;
if (ide_system_bus_speed()<=33) {
active_cycle = 9 - IDE_IN(active_time * ide_system_bus_speed() / 1000 + 1, 2, 9);
recovery_cycle = 15 - IDE_IN(recovery_time * ide_system_bus_speed() / 1000 + 1, 0, 15);
if (system_bus_clock()<=33) {
active_cycle = 9 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 9);
recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 0, 15);
} else {
active_cycle = 8 - IDE_IN(active_time * ide_system_bus_speed() / 1000 + 1, 1, 8);
recovery_cycle = 18 - IDE_IN(recovery_time * ide_system_bus_speed() / 1000 + 1, 3, 18);
active_cycle = 8 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 1, 8);
recovery_cycle = 18 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 3, 18);
}
return((recovery_cycle<<4) | 0x08 | active_cycle);
......@@ -154,10 +164,10 @@ static byte qd6500_compute_timing (ide_hwif_t *hwif, int active_time, int recove
* idem for qd6580
*/
static byte qd6580_compute_timing (int active_time, int recovery_time)
static u8 qd6580_compute_timing (int active_time, int recovery_time)
{
byte active_cycle = 17-IDE_IN(active_time * ide_system_bus_speed() / 1000 + 1, 2, 17);
byte recovery_cycle = 15-IDE_IN(recovery_time * ide_system_bus_speed() / 1000 + 1, 2, 15);
u8 active_cycle = 17 - IDE_IN(active_time * system_bus_clock() / 1000 + 1, 2, 17);
u8 recovery_cycle = 15 - IDE_IN(recovery_time * system_bus_clock() / 1000 + 1, 2, 15);
return((recovery_cycle<<4) | active_cycle);
}
......@@ -180,8 +190,8 @@ static int qd_find_disk_type (ide_drive_t *drive,
ide_fixstring(model,40,1); /* byte-swap */
for (p = qd65xx_timing ; p->offset != -1 ; p++) {
if (!strncmp(p->model, model+p->offset,4)) {
printk(KERN_DEBUG "%s: listed !\n",drive->name);
if (!strncmp(p->model, model+p->offset, 4)) {
printk(KERN_DEBUG "%s: listed !\n", drive->name);
*active_time = p->active;
*recovery_time = p->recovery;
return 1;
......@@ -210,7 +220,7 @@ static int qd_timing_ok (ide_drive_t drives[])
* records the timing, and enables selectproc as needed
*/
static void qd_set_timing (ide_drive_t *drive, byte timing)
static void qd_set_timing (ide_drive_t *drive, u8 timing)
{
ide_hwif_t *hwif = HWIF(drive);
......@@ -222,19 +232,19 @@ static void qd_set_timing (ide_drive_t *drive, byte timing)
} else
hwif->selectproc = &qd_select;
printk(KERN_DEBUG "%s: %#x\n",drive->name,timing);
printk(KERN_DEBUG "%s: %#x\n", drive->name, timing);
}
/*
* qd6500_tune_drive
*/
static void qd6500_tune_drive (ide_drive_t *drive, byte pio)
static void qd6500_tune_drive (ide_drive_t *drive, u8 pio)
{
int active_time = 175;
int recovery_time = 415; /* worst case values from the dos driver */
if (drive->id && !qd_find_disk_type(drive,&active_time,&recovery_time)
if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)
&& drive->id->tPIO && (drive->id->field_valid & 0x02)
&& drive->id->eide_pio >= 240) {
......@@ -244,21 +254,21 @@ static void qd6500_tune_drive (ide_drive_t *drive, byte pio)
recovery_time = drive->id->eide_pio - 120;
}
qd_set_timing(drive,qd6500_compute_timing(HWIF(drive),active_time,recovery_time));
qd_set_timing(drive, qd6500_compute_timing(HWIF(drive), active_time, recovery_time));
}
/*
* qd6580_tune_drive
*/
static void qd6580_tune_drive (ide_drive_t *drive, byte pio)
static void qd6580_tune_drive (ide_drive_t *drive, u8 pio)
{
ide_pio_data_t d;
int base = HWIF(drive)->select_data;
int active_time = 175;
int recovery_time = 415; /* worst case values from the dos driver */
if (drive->id && !qd_find_disk_type(drive,&active_time,&recovery_time)) {
if (drive->id && !qd_find_disk_type(drive, &active_time, &recovery_time)) {
pio = ide_get_best_pio_mode(drive, pio, 255, &d);
pio = IDE_MIN(pio,4);
......@@ -267,14 +277,14 @@ static void qd6580_tune_drive (ide_drive_t *drive, byte pio)
case 3:
if (d.cycle_time >= 110) {
active_time = 86;
recovery_time = d.cycle_time-102;
recovery_time = d.cycle_time - 102;
} else
printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name);
break;
case 4:
if (d.cycle_time >= 69) {
active_time = 70;
recovery_time = d.cycle_time-61;
recovery_time = d.cycle_time - 61;
} else
printk(KERN_WARNING "%s: Strange recovery time !\n",drive->name);
break;
......@@ -288,15 +298,17 @@ static void qd6580_tune_drive (ide_drive_t *drive, byte pio)
-active_time;
}
}
printk(KERN_INFO "%s: PIO mode%d\n",drive->name,pio);
printk(KERN_INFO "%s: PIO mode%d\n", drive->name,pio);
}
if (!HWIF(drive)->channel && drive->media != ide_disk) {
qd_write_reg(0x5f,QD_CONTROL_PORT);
printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO and post-write buffer on %s.\n",drive->name,HWIF(drive)->name);
qd_write_reg(0x5f, QD_CONTROL_PORT);
printk(KERN_WARNING "%s: ATAPI: disabled read-ahead FIFO "
"and post-write buffer on %s.\n",
drive->name, HWIF(drive)->name);
}
qd_set_timing(drive,qd6580_compute_timing(active_time,recovery_time));
qd_set_timing(drive, qd6580_compute_timing(active_time, recovery_time));
}
/*
......@@ -307,15 +319,15 @@ static void qd6580_tune_drive (ide_drive_t *drive, byte pio)
static int __init qd_testreg(int port)
{
byte savereg;
byte readreg;
u8 savereg;
u8 readreg;
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
savereg = inb_p(port);
outb_p(QD_TESTVAL,port); /* safe value */
outb_p(QD_TESTVAL, port); /* safe value */
readreg = inb_p(port);
OUT_BYTE(savereg,port);
outb(savereg, port);
spin_unlock_irqrestore(&ide_lock, flags);
if (savereg == QD_TESTVAL) {
......@@ -329,32 +341,91 @@ static int __init qd_testreg(int port)
}
/*
* probe:
* qd_setup:
*
* called to setup an ata channel : adjusts attributes & links for tuning
*/
void __init qd_setup (int unit, int base, int config, unsigned int data0, unsigned int data1, void (*tuneproc) (ide_drive_t *, u8 pio))
{
ide_hwif_t *hwif = &ide_hwifs[unit];
hwif->chipset = ide_qd65xx;
hwif->channel = unit;
hwif->select_data = base;
hwif->config_data = config;
hwif->drives[0].drive_data = data0;
hwif->drives[1].drive_data = data1;
hwif->drives[0].io_32bit =
hwif->drives[1].io_32bit = 1;
hwif->tuneproc = tuneproc;
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init(hwif);
#endif /* HWIF_PROBE_CLASSIC_METHOD */
}
/*
* qd_unsetup:
*
* called to unsetup an ata channel : back to default values, unlinks tuning
*/
void __init qd_unsetup (int unit)
{
ide_hwif_t *hwif = &ide_hwifs[unit];
u8 config = hwif->config_data;
int base = hwif->select_data;
void *tuneproc = (void *) hwif->tuneproc;
if (!(hwif->chipset == ide_qd65xx)) return;
printk(KERN_NOTICE "%s: back to defaults\n", hwif->name);
hwif->selectproc = NULL;
hwif->tuneproc = NULL;
if (tuneproc == (void *) qd6500_tune_drive) {
// will do it for both
qd_write_reg(QD6500_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
} else if (tuneproc == (void *) qd6580_tune_drive) {
if (QD_CONTROL(hwif) & QD_CONTR_SEC_DISABLED) {
qd_write_reg(QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
qd_write_reg(QD6580_DEF_DATA2, QD_TIMREG(&hwif->drives[1]));
} else {
qd_write_reg(unit?QD6580_DEF_DATA2:QD6580_DEF_DATA, QD_TIMREG(&hwif->drives[0]));
}
} else {
printk(KERN_WARNING "Unknown qd65xx tuning fonction !\n");
printk(KERN_WARNING "keeping settings !\n");
}
}
/*
* qd_probe:
*
* looks at the specified baseport, and if qd found, registers & initialises it
* return 1 if another qd may be probed
*/
int __init probe (int base)
int __init qd_probe (int base)
{
byte config;
byte index;
u8 config;
u8 unit;
config = qd_read_reg(QD_CONFIG_PORT);
if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) ) return 1;
if (! ((config & QD_CONFIG_BASEPORT) >> 1 == (base == 0xb0)) )
return 1;
index = ! (config & QD_CONFIG_IDE_BASEPORT);
unit = ! (config & QD_CONFIG_IDE_BASEPORT);
if ((config & 0xf0) == QD_CONFIG_QD6500) {
ide_hwif_t *hwif = &ide_hwifs[index];
if (qd_testreg(base)) return 1; /* bad register */
/* qd6500 found */
printk(KERN_NOTICE "%s: qd6500 at %#x\n",
ide_hwifs[index].name, base);
ide_hwifs[unit].name, base);
printk(KERN_DEBUG "qd6500: config=%#x, ID3=%u\n",
config, QD_ID3);
......@@ -364,20 +435,15 @@ int __init probe (int base)
return 1;
}
hwif->chipset = ide_qd65xx;
hwif->select_data = base;
hwif->config_data = config;
hwif->drives[0].drive_data =
hwif->drives[1].drive_data = QD6500_DEF_DATA;
hwif->drives[0].io_32bit =
hwif->drives[1].io_32bit = 1;
hwif->tuneproc = &qd6500_tune_drive;
qd_setup(unit, base, config, QD6500_DEF_DATA,
QD6500_DEF_DATA, &qd6500_tune_drive);
return 1;
}
if (((config & 0xf0) == QD_CONFIG_QD6580_A) || ((config & 0xf0) == QD_CONFIG_QD6580_B)) {
if (((config & 0xf0) == QD_CONFIG_QD6580_A) ||
((config & 0xf0) == QD_CONFIG_QD6580_B)) {
byte control;
u8 control;
if (qd_testreg(base) || qd_testreg(base+0x02)) return 1;
/* bad registers */
......@@ -391,47 +457,26 @@ int __init probe (int base)
config, control, QD_ID3);
if (control & QD_CONTR_SEC_DISABLED) {
ide_hwif_t *hwif = &ide_hwifs[index];
/* secondary disabled */
printk(KERN_INFO "%s: qd6580: single IDE board\n",
ide_hwifs[index].name);
hwif->chipset = ide_qd65xx;
hwif->select_data = base;
hwif->config_data = config | (control <<8);
hwif->drives[0].drive_data =
hwif->drives[1].drive_data = QD6580_DEF_DATA;
hwif->drives[0].io_32bit =
hwif->drives[1].io_32bit = 1;
hwif->tuneproc = &qd6580_tune_drive;
ide_hwifs[unit].name);
qd_setup(unit, base, config | (control << 8),
QD6580_DEF_DATA, QD6580_DEF_DATA2,
&qd6580_tune_drive);
qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT);
return 1;
} else {
int i,j;
/* secondary enabled */
printk(KERN_INFO "%s&%s: qd6580: dual IDE board\n",
ide_hwifs[0].name,ide_hwifs[1].name);
for (i=0;i<2;i++) {
ide_hwifs[i].chipset = ide_qd65xx;
ide_hwifs[i].mate = &ide_hwifs[i^1];
ide_hwifs[i].channel = i;
ide_hwifs[i].select_data = base;
ide_hwifs[i].config_data = config | (control <<8);
ide_hwifs[i].tuneproc = &qd6580_tune_drive;
for (j=0;j<2;j++) {
ide_hwifs[i].drives[j].drive_data =
i?QD6580_DEF_DATA2:QD6580_DEF_DATA;
ide_hwifs[i].drives[j].io_32bit = 1;
}
}
qd_setup(0, base, config | (control << 8),
QD6580_DEF_DATA, QD6580_DEF_DATA,
&qd6580_tune_drive);
qd_setup(1, base, config | (control << 8),
QD6580_DEF_DATA2, QD6580_DEF_DATA2,
&qd6580_tune_drive);
qd_write_reg(QD_DEF_CONTR,QD_CONTROL_PORT);
return 0; /* no other qd65xx possible */
......@@ -441,13 +486,38 @@ int __init probe (int base)
return 1;
}
#ifndef MODULE
/*
* init_qd65xx:
*
* called at the very beginning of initialization ; should just probe and link
* called by ide.c when parsing command line
*/
void __init init_qd65xx (void)
{
if (probe(0x30)) probe(0xb0);
if (qd_probe(0x30)) qd_probe(0xb0);
}
#else
MODULE_AUTHOR("Samuel Thibault");
MODULE_DESCRIPTION("support of qd65xx vlb ide chipset");
MODULE_LICENSE("GPL");
int __init qd65xx_mod_init(void)
{
if (qd_probe(0x30)) qd_probe(0xb0);
if (ide_hwifs[0].chipset != ide_qd65xx &&
ide_hwifs[1].chipset != ide_qd65xx)
return -ENODEV;
return 0;
}
module_init(qd65xx_mod_init);
void __init qd65xx_mod_exit(void)
{
qd_unsetup(0);
qd_unsetup(1);
}
module_exit(qd65xx_mod_exit);
#endif
......@@ -39,6 +39,8 @@
*/
#define REALLY_SLOW_IO /* some systems can safely undef this */
#include <linux/module.h>
#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
......@@ -52,7 +54,13 @@
#include <asm/io.h>
#include "ide_modes.h"
#ifdef CONFIG_BLK_DEV_UMC8672_MODULE
# define _IDE_C
# include "ide_modes.h"
# undef _IDE_C
#else
# include "ide_modes.h"
#endif /* CONFIG_BLK_DEV_UMC8672_MODULE */
/*
* Default speeds. These can be changed with "auto-tune" and/or hdparm.
......@@ -62,11 +70,11 @@
#define UMC_DRIVE2 1 /* 11 = Fastest Speed */
#define UMC_DRIVE3 1 /* In case of crash reduce speed */
static byte current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
static const byte pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */
static u8 current_speeds[4] = {UMC_DRIVE0, UMC_DRIVE1, UMC_DRIVE2, UMC_DRIVE3};
static const u8 pio_to_umc [5] = {0,3,7,10,11}; /* rough guesses */
/* 0 1 2 3 4 5 6 7 8 9 10 11 */
static const byte speedtab [3][12] = {
static const u8 speedtab [3][12] = {
{0xf, 0xb, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
{0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1 },
{0xff,0xcb,0xc0,0x58,0x36,0x33,0x23,0x22,0x21,0x11,0x10,0x0}};
......@@ -77,13 +85,13 @@ static void out_umc (char port,char wert)
outb_p(wert,0x109);
}
static inline byte in_umc (char port)
static inline u8 in_umc (char port)
{
outb_p(port,0x108);
return inb_p(0x109);
}
static void umc_set_speeds (byte speeds[])
static void umc_set_speeds (u8 speeds[])
{
int i, tmp;
......@@ -106,7 +114,7 @@ static void umc_set_speeds (byte speeds[])
speeds[0], speeds[1], speeds[2], speeds[3]);
}
static void tune_umc (ide_drive_t *drive, byte pio)
static void tune_umc (ide_drive_t *drive, u8 pio)
{
unsigned long flags;
ide_hwgroup_t *hwgroup = ide_hwifs[HWIF(drive)->index^1].hwgroup;
......@@ -116,7 +124,7 @@ static void tune_umc (ide_drive_t *drive, byte pio)
drive->name, pio, pio_to_umc[pio]);
spin_lock_irqsave(&ide_lock, flags);
if (hwgroup && hwgroup->handler != NULL) {
printk("umc8672: other interface is busy: exiting tune_umc()\n");
printk(KERN_ERR "umc8672: other interface is busy: exiting tune_umc()\n");
} else {
current_speeds[drive->name[2] - 'a'] = pio_to_umc[pio];
umc_set_speeds (current_speeds);
......@@ -124,21 +132,21 @@ static void tune_umc (ide_drive_t *drive, byte pio)
spin_unlock_irqrestore(&ide_lock, flags);
}
void __init init_umc8672 (void) /* called from ide.c */
int __init probe_umc8672 (void)
{
unsigned long flags;
local_irq_save(flags);
if (check_region(0x108, 2)) {
local_irq_restore(flags);
printk("\numc8672: PORTS 0x108-0x109 ALREADY IN USE\n");
return;
printk(KERN_ERR "umc8672: ports 0x108-0x109 already in use.\n");
return 1;
}
outb_p(0x5A,0x108); /* enable umc */
if (in_umc (0xd5) != 0xa0) {
local_irq_restore(flags);
printk ("umc8672: not found\n");
return;
printk(KERN_ERR "umc8672: not found\n");
return 1;
}
outb_p(0xa5,0x108); /* disable umc */
......@@ -153,4 +161,77 @@ void __init init_umc8672 (void) /* called from ide.c */
ide_hwifs[0].mate = &ide_hwifs[1];
ide_hwifs[1].mate = &ide_hwifs[0];
ide_hwifs[1].channel = 1;
#ifndef HWIF_PROBE_CLASSIC_METHOD
probe_hwif_init(&ide_hwifs[0]);
probe_hwif_init(&ide_hwifs[1]);
#endif /* HWIF_PROBE_CLASSIC_METHOD */
return 0;
}
void __init umc8672_release (void)
{
unsigned long flags;
local_irq_save(flags);
if (ide_hwifs[0].chipset != ide_umc8672 &&
ide_hwifs[1].chipset != ide_umc8672) {
local_irq_restore(flags);
return;
}
ide_hwifs[0].chipset = ide_unknown;
ide_hwifs[1].chipset = ide_unknown;
ide_hwifs[0].tuneproc = NULL;
ide_hwifs[1].tuneproc = NULL;
ide_hwifs[0].mate = NULL;
ide_hwifs[1].mate = NULL;
ide_hwifs[0].channel = 0;
ide_hwifs[1].channel = 0;
outb_p(0xa5,0x108); /* disable umc */
release_region(0x108, 2);
local_irq_restore(flags);
}
#ifndef MODULE
/*
* init_umc8672:
*
* called by ide.c when parsing command line
*/
void __init init_umc8672 (void)
{
if (probe_umc8672())
printk(KERN_ERR "init_umc8672: umc8672 controller not found.\n");
}
#else
MODULE_AUTHOR("Wolfram Podien");
MODULE_DESCRIPTION("Support for UMC 8672 IDE chipset");
MODULE_LICENSE("GPL");
int __init umc8672_mod_init(void)
{
if (probe_umc8672())
return -ENODEV;
if (ide_hwifs[0].chipset != ide_umc8672 &&
ide_hwifs[1].chipset != ide_umc8672) {
umc8672_release();
return -ENODEV;
}
return 0;
}
module_init(umc8672_mod_init);
void __init umc8672_mod_exit(void)
{
umc8672_release();
}
module_exit(umc8672_mod_exit);
#endif
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