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