Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (35 commits)
  siimage: coding style cleanup (take 2)
  ide-cd: clean up cdrom_analyze_sense_data()
  ide-cd: fix test unsigned var < 0
  ide: add TSSTcorp CDDVDW SH-S202H to ivb_list[]
  piix: add Asus Eee 701 controller to short cable list
  ARM: always select HAVE_IDE
  remove the broken ETRAX_IDE driver
  ide: remove ->dma_prdtable field from ide_hwif_t
  ide: remove ->dma_vendor{1,3} fields from ide_hwif_t
  scc_pata: add ->dma_host_set and ->dma_start methods
  ide: skip "VLB sync" if host uses MMIO
  ide: add ide_pad_transfer() helper
  ide: remove ->INW and ->OUTW methods
  ide: use IDE I/O helpers directly in ide_tf_{load,read}()
  ns87415: add ->tf_read method
  scc_pata: add ->tf_{load,read} methods
  ide-h8300: add ->tf_{load,read} methods
  ide-cris: add ->tf_{load,read} methods
  ide: add ->tf_load and ->tf_read methods
  ide: move ide_tf_{load,read} to ide-iops.c
  ...
This commit is contained in:
Linus Torvalds 2008-04-28 17:30:26 -07:00
commit 8ab68ab420
33 changed files with 961 additions and 1826 deletions

View file

@ -8,6 +8,7 @@ mainmenu "Linux Kernel Configuration"
config ARM config ARM
bool bool
default y default y
select HAVE_IDE
select RTC_LIB select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION select SYS_SUPPORTS_APM_EMULATION
select HAVE_OPROFILE select HAVE_OPROFILE
@ -223,7 +224,6 @@ config ARCH_CLPS7500
select TIMER_ACORN select TIMER_ACORN
select ISA select ISA
select NO_IOPORT select NO_IOPORT
select HAVE_IDE
help help
Support for the Cirrus Logic PS7500FE system-on-a-chip. Support for the Cirrus Logic PS7500FE system-on-a-chip.
@ -236,7 +236,6 @@ config ARCH_CO285
bool "Co-EBSA285" bool "Co-EBSA285"
select FOOTBRIDGE select FOOTBRIDGE
select FOOTBRIDGE_ADDIN select FOOTBRIDGE_ADDIN
select HAVE_IDE
help help
Support for Intel's EBSA285 companion chip. Support for Intel's EBSA285 companion chip.
@ -262,7 +261,6 @@ config ARCH_EP93XX
config ARCH_FOOTBRIDGE config ARCH_FOOTBRIDGE
bool "FootBridge" bool "FootBridge"
select FOOTBRIDGE select FOOTBRIDGE
select HAVE_IDE
help help
Support for systems based on the DC21285 companion chip Support for systems based on the DC21285 companion chip
("FootBridge"), such as the Simtec CATS and the Rebel NetWinder. ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
@ -301,7 +299,6 @@ config ARCH_IOP32X
depends on MMU depends on MMU
select PLAT_IOP select PLAT_IOP
select PCI select PCI
select HAVE_IDE
help help
Support for Intel's 80219 and IOP32X (XScale) family of Support for Intel's 80219 and IOP32X (XScale) family of
processors. processors.
@ -311,14 +308,12 @@ config ARCH_IOP33X
depends on MMU depends on MMU
select PLAT_IOP select PLAT_IOP
select PCI select PCI
select HAVE_IDE
help help
Support for Intel's IOP33X (XScale) family of processors. Support for Intel's IOP33X (XScale) family of processors.
config ARCH_IXP23XX config ARCH_IXP23XX
bool "IXP23XX-based" bool "IXP23XX-based"
depends on MMU depends on MMU
select HAVE_IDE
select PCI select PCI
help help
Support for Intel's IXP23xx (XScale) family of processors. Support for Intel's IXP23xx (XScale) family of processors.
@ -336,14 +331,12 @@ config ARCH_IXP4XX
select GENERIC_GPIO select GENERIC_GPIO
select GENERIC_TIME select GENERIC_TIME
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select HAVE_IDE
help help
Support for Intel's IXP4XX (XScale) family of processors. Support for Intel's IXP4XX (XScale) family of processors.
config ARCH_L7200 config ARCH_L7200
bool "LinkUp-L7200" bool "LinkUp-L7200"
select FIQ select FIQ
select HAVE_IDE
help help
Say Y here if you intend to run this kernel on a LinkUp Systems Say Y here if you intend to run this kernel on a LinkUp Systems
L7200 Software Development Board which uses an ARM720T processor. L7200 Software Development Board which uses an ARM720T processor.
@ -400,7 +393,6 @@ config ARCH_PXA
depends on MMU depends on MMU
select ARCH_MTD_XIP select ARCH_MTD_XIP
select GENERIC_GPIO select GENERIC_GPIO
select HAVE_IDE
select HAVE_GPIO_LIB select HAVE_GPIO_LIB
select GENERIC_TIME select GENERIC_TIME
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
@ -416,7 +408,6 @@ config ARCH_RPC
select ARCH_MAY_HAVE_PC_FDC select ARCH_MAY_HAVE_PC_FDC
select ISA_DMA_API select ISA_DMA_API
select NO_IOPORT select NO_IOPORT
select HAVE_IDE
help help
On the Acorn Risc-PC, Linux can support the internal IDE disk and On the Acorn Risc-PC, Linux can support the internal IDE disk and
CD-ROM interface, serial and parallel port, and the floppy drive. CD-ROM interface, serial and parallel port, and the floppy drive.
@ -432,7 +423,6 @@ config ARCH_SA1100
select GENERIC_TIME select GENERIC_TIME
select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS
select TICK_ONESHOT select TICK_ONESHOT
select HAVE_IDE
select HAVE_GPIO_LIB select HAVE_GPIO_LIB
help help
Support for StrongARM 11x0 based boards. Support for StrongARM 11x0 based boards.
@ -440,7 +430,6 @@ config ARCH_SA1100
config ARCH_S3C2410 config ARCH_S3C2410
bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443" bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
select GENERIC_GPIO select GENERIC_GPIO
select HAVE_IDE
help help
Samsung S3C2410X CPU based systems, such as the Simtec Electronics Samsung S3C2410X CPU based systems, such as the Simtec Electronics
BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or BAST (<http://www.simtec.co.uk/products/EB110ITX/>), the IPAQ 1940 or
@ -448,7 +437,6 @@ config ARCH_S3C2410
config ARCH_SHARK config ARCH_SHARK
bool "Shark" bool "Shark"
select HAVE_IDE
select ISA select ISA
select ISA_DMA select ISA_DMA
select PCI select PCI
@ -458,7 +446,6 @@ config ARCH_SHARK
config ARCH_LH7A40X config ARCH_LH7A40X
bool "Sharp LH7A40X" bool "Sharp LH7A40X"
select HAVE_IDE
help help
Say Y here for systems based on one of the Sharp LH7A40X Say Y here for systems based on one of the Sharp LH7A40X
System on a Chip processors. These CPUs include an ARM922T System on a Chip processors. These CPUs include an ARM922T

View file

@ -862,40 +862,6 @@ config BLK_DEV_IDE_BAST
Say Y here if you want to support the onboard IDE channels on the Say Y here if you want to support the onboard IDE channels on the
Simtec BAST or the Thorcom VR1000 Simtec BAST or the Thorcom VR1000
config ETRAX_IDE
tristate "ETRAX IDE support"
depends on CRIS && BROKEN
select BLK_DEV_IDEDMA
help
Enables the ETRAX IDE driver.
You can't use parallel ports or SCSI ports at the same time.
config ETRAX_IDE_DELAY
int "Delay for drives to regain consciousness"
depends on ETRAX_IDE && ETRAX_ARCH_V10
default 15
help
Number of seconds to wait for IDE drives to spin up after an IDE
reset.
choice
prompt "IDE reset pin"
depends on ETRAX_IDE && ETRAX_ARCH_V10
default ETRAX_IDE_PB7_RESET
config ETRAX_IDE_PB7_RESET
bool "Port_PB_Bit_7"
help
IDE reset on pin 7 on port B
config ETRAX_IDE_G27_RESET
bool "Port_G_Bit_27"
help
IDE reset on pin 27 on port G
endchoice
config IDE_H8300 config IDE_H8300
tristate "H8300 IDE support" tristate "H8300 IDE support"
depends on H8300 depends on H8300

View file

@ -35,7 +35,7 @@ ifeq ($(CONFIG_BLK_DEV_CMD640), y)
obj-y += cmd640-core.o obj-y += cmd640-core.o
endif endif
obj-$(CONFIG_BLK_DEV_IDE) += cris/ ppc/ obj-$(CONFIG_BLK_DEV_IDE) += ppc/
obj-$(CONFIG_IDE_H8300) += h8300/ obj-$(CONFIG_IDE_H8300) += h8300/
obj-$(CONFIG_IDE_GENERIC) += ide-generic.o obj-$(CONFIG_IDE_GENERIC) += ide-generic.o
obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o obj-$(CONFIG_BLK_DEV_IDEPNP) += ide-pnp.o

View file

@ -483,7 +483,7 @@ static const struct ide_port_info icside_v6_port_info __initdata = {
.init_dma = icside_dma_off_init, .init_dma = icside_dma_off_init,
.port_ops = &icside_v6_no_dma_port_ops, .port_ops = &icside_v6_no_dma_port_ops,
.dma_ops = &icside_v6_dma_ops, .dma_ops = &icside_v6_dma_ops,
.host_flags = IDE_HFLAG_SERIALIZE, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO,
.mwdma_mask = ATA_MWDMA2, .mwdma_mask = ATA_MWDMA2,
.swdma_mask = ATA_SWDMA2, .swdma_mask = ATA_SWDMA2,
}; };

View file

@ -342,6 +342,7 @@ static const struct ide_port_ops palm_bk3710_ports_ops = {
static const struct ide_port_info __devinitdata palm_bk3710_port_info = { static const struct ide_port_info __devinitdata palm_bk3710_port_info = {
.init_dma = palm_bk3710_init_dma, .init_dma = palm_bk3710_init_dma,
.port_ops = &palm_bk3710_ports_ops, .port_ops = &palm_bk3710_ports_ops,
.host_flags = IDE_HFLAG_MMIO,
.pio_mask = ATA_PIO4, .pio_mask = ATA_PIO4,
.udma_mask = ATA_UDMA4, /* (input clk 99MHz) */ .udma_mask = ATA_UDMA4, /* (input clk 99MHz) */
.mwdma_mask = ATA_MWDMA2, .mwdma_mask = ATA_MWDMA2,

View file

@ -53,6 +53,7 @@ rapide_probe(struct expansion_card *ec, const struct ecard_id *id)
ide_init_port_hw(hwif, &hw); ide_init_port_hw(hwif, &hw);
hwif->host_flags = IDE_HFLAG_MMIO;
default_hwif_mmiops(hwif); default_hwif_mmiops(hwif);
idx[0] = hwif->index; idx[0] = hwif->index;

View file

@ -1,3 +0,0 @@
EXTRA_CFLAGS += -Idrivers/ide
obj-$(CONFIG_IDE_ETRAX) += ide-cris.o

File diff suppressed because it is too large Load diff

View file

@ -42,6 +42,91 @@ static u16 mm_inw(unsigned long a)
return r; return r;
} }
static void h8300_tf_load(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
struct ide_taskfile *tf = &task->tf;
u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
if (task->tf_flags & IDE_TFLAG_FLAGGED)
HIHI = 0xFF;
ide_set_irq(drive, 1);
if (task->tf_flags & IDE_TFLAG_OUT_DATA)
mm_outw((tf->hob_data << 8) | tf->data, io_ports->data_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
outb(tf->hob_feature, io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
outb(tf->hob_nsect, io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
outb(tf->hob_lbal, io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
outb(tf->hob_lbam, io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
outb(tf->hob_lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
outb(tf->feature, io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
outb(tf->nsect, io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
outb(tf->lbal, io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
outb(tf->lbam, io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
outb(tf->lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
outb((tf->device & HIHI) | drive->select.all,
io_ports->device_addr);
}
static void h8300_tf_read(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
struct ide_taskfile *tf = &task->tf;
if (task->tf_flags & IDE_TFLAG_IN_DATA) {
u16 data = mm_inw(io_ports->data_addr);
tf->data = data & 0xff;
tf->hob_data = (data >> 8) & 0xff;
}
/* be sure we're looking at the low order bits */
outb(drive->ctl & ~0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
tf->lbal = inb(io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAM)
tf->lbam = inb(io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAH)
tf->lbah = inb(io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
tf->device = inb(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
outb(drive->ctl | 0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
tf->hob_nsect = inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
tf->hob_lbal = inb(io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
tf->hob_lbam = inb(io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
tf->hob_lbah = inb(io_ports->lbah_addr);
}
}
static void mm_outsw(unsigned long addr, void *buf, u32 len) static void mm_outsw(unsigned long addr, void *buf, u32 len)
{ {
unsigned short *bp = (unsigned short *)buf; unsigned short *bp = (unsigned short *)buf;
@ -56,6 +141,18 @@ static void mm_insw(unsigned long addr, void *buf, u32 len)
*bp = bswap(*(volatile u16 *)addr); *bp = bswap(*(volatile u16 *)addr);
} }
static void h8300_input_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{
mm_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
static void h8300_output_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{
mm_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
#define H8300_IDE_GAP (2) #define H8300_IDE_GAP (2)
static inline void hw_setup(hw_regs_t *hw) static inline void hw_setup(hw_regs_t *hw)
@ -74,12 +171,11 @@ static inline void hwif_setup(ide_hwif_t *hwif)
{ {
default_hwif_iops(hwif); default_hwif_iops(hwif);
hwif->OUTW = mm_outw; hwif->tf_load = h8300_tf_load;
hwif->OUTSW = mm_outsw; hwif->tf_read = h8300_tf_read;
hwif->INW = mm_inw;
hwif->INSW = mm_insw; hwif->input_data = h8300_input_data;
hwif->OUTSL = NULL; hwif->output_data = h8300_output_data;
hwif->INSL = NULL;
} }
static int __init h8300_ide_init(void) static int __init h8300_ide_init(void)

View file

@ -142,7 +142,6 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
{ {
unsigned long sector; unsigned long sector;
unsigned long bio_sectors; unsigned long bio_sectors;
unsigned long valid;
struct cdrom_info *info = drive->driver_data; struct cdrom_info *info = drive->driver_data;
if (!cdrom_log_sense(drive, failed_command, sense)) if (!cdrom_log_sense(drive, failed_command, sense))
@ -173,17 +172,13 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive,
(sense->information[2] << 8) | (sense->information[2] << 8) |
(sense->information[3]); (sense->information[3]);
bio_sectors = bio_sectors(failed_command->bio);
if (bio_sectors < 4)
bio_sectors = 4;
if (drive->queue->hardsect_size == 2048) if (drive->queue->hardsect_size == 2048)
/* device sector size is 2K */ /* device sector size is 2K */
sector <<= 2; sector <<= 2;
sector &= ~(bio_sectors - 1);
valid = (sector - failed_command->sector) << 9;
if (valid < 0) bio_sectors = max(bio_sectors(failed_command->bio), 4U);
valid = 0; sector &= ~(bio_sectors - 1);
if (sector < get_capacity(info->disk) && if (sector < get_capacity(info->disk) &&
drive->probed_capacity - sector < 4 * 75) drive->probed_capacity - sector < 4 * 75)
set_capacity(info->disk, sector); set_capacity(info->disk, sector);
@ -555,14 +550,7 @@ static ide_startstop_t cdrom_start_packet_command(ide_drive_t *drive,
ATAPI_WAIT_PC, cdrom_timer_expiry); ATAPI_WAIT_PC, cdrom_timer_expiry);
return ide_started; return ide_started;
} else { } else {
unsigned long flags; ide_execute_pkt_cmd(drive);
/* packet command */
spin_lock_irqsave(&ide_lock, flags);
hwif->OUTBSYNC(drive, WIN_PACKETCMD,
hwif->io_ports.command_addr);
ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags);
return (*handler) (drive); return (*handler) (drive);
} }
@ -613,7 +601,7 @@ static ide_startstop_t cdrom_transfer_packet_command(ide_drive_t *drive,
cmd_len = ATAPI_MIN_CDB_BYTES; cmd_len = ATAPI_MIN_CDB_BYTES;
/* send the command to the device */ /* send the command to the device */
HWIF(drive)->atapi_output_bytes(drive, rq->cmd, cmd_len); hwif->output_data(drive, NULL, rq->cmd, cmd_len);
/* start the DMA if need be */ /* start the DMA if need be */
if (info->dma) if (info->dma)
@ -629,7 +617,7 @@ static void ide_cd_pad_transfer(ide_drive_t *drive, xfer_func_t *xf, int len)
{ {
while (len > 0) { while (len > 0) {
int dum = 0; int dum = 0;
xf(drive, &dum, sizeof(dum)); xf(drive, NULL, &dum, sizeof(dum));
len -= sizeof(dum); len -= sizeof(dum);
} }
} }
@ -639,7 +627,7 @@ static void ide_cd_drain_data(ide_drive_t *drive, int nsects)
while (nsects > 0) { while (nsects > 0) {
static char dum[SECTOR_SIZE]; static char dum[SECTOR_SIZE];
drive->hwif->atapi_input_bytes(drive, dum, sizeof(dum)); drive->hwif->input_data(drive, NULL, dum, sizeof(dum));
nsects--; nsects--;
} }
} }
@ -666,7 +654,7 @@ static int ide_cd_check_ireason(ide_drive_t *drive, struct request *rq,
printk(KERN_ERR "%s: %s: wrong transfer direction!\n", printk(KERN_ERR "%s: %s: wrong transfer direction!\n",
drive->name, __func__); drive->name, __func__);
xf = rw ? hwif->atapi_output_bytes : hwif->atapi_input_bytes; xf = rw ? hwif->output_data : hwif->input_data;
ide_cd_pad_transfer(drive, xf, len); ide_cd_pad_transfer(drive, xf, len);
} else if (rw == 0 && ireason == 1) { } else if (rw == 0 && ireason == 1) {
/* /*
@ -1019,10 +1007,10 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (ireason == 0) { if (ireason == 0) {
write = 1; write = 1;
xferfunc = HWIF(drive)->atapi_output_bytes; xferfunc = hwif->output_data;
} else { } else {
write = 0; write = 0;
xferfunc = HWIF(drive)->atapi_input_bytes; xferfunc = hwif->input_data;
} }
/* transfer data */ /* transfer data */
@ -1061,7 +1049,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive)
if (blen > thislen) if (blen > thislen)
blen = thislen; blen = thislen;
xferfunc(drive, ptr, blen); xferfunc(drive, NULL, ptr, blen);
thislen -= blen; thislen -= blen;
len -= blen; len -= blen;

View file

@ -464,9 +464,10 @@ int ide_dma_setup(ide_drive_t *drive)
/* PRD table */ /* PRD table */
if (hwif->mmio) if (hwif->mmio)
writel(hwif->dmatable_dma, (void __iomem *)hwif->dma_prdtable); writel(hwif->dmatable_dma,
(void __iomem *)(hwif->dma_base + ATA_DMA_TABLE_OFS));
else else
outl(hwif->dmatable_dma, hwif->dma_prdtable); outl(hwif->dmatable_dma, hwif->dma_base + ATA_DMA_TABLE_OFS);
/* specify r/w */ /* specify r/w */
hwif->OUTB(reading, hwif->dma_command); hwif->OUTB(reading, hwif->dma_command);
@ -858,14 +859,8 @@ void ide_setup_dma(ide_hwif_t *hwif, unsigned long base)
if (!hwif->dma_command) if (!hwif->dma_command)
hwif->dma_command = hwif->dma_base + 0; hwif->dma_command = hwif->dma_base + 0;
if (!hwif->dma_vendor1)
hwif->dma_vendor1 = hwif->dma_base + 1;
if (!hwif->dma_status) if (!hwif->dma_status)
hwif->dma_status = hwif->dma_base + 2; hwif->dma_status = hwif->dma_base + 2;
if (!hwif->dma_vendor3)
hwif->dma_vendor3 = hwif->dma_base + 3;
if (!hwif->dma_prdtable)
hwif->dma_prdtable = hwif->dma_base + 4;
hwif->dma_ops = &sff_dma_ops; hwif->dma_ops = &sff_dma_ops;
} }

View file

@ -231,6 +231,7 @@ static int idefloppy_end_request(ide_drive_t *drive, int uptodate, int nsecs)
static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount, int direction) unsigned int bcount, int direction)
{ {
ide_hwif_t *hwif = drive->hwif;
struct request *rq = pc->rq; struct request *rq = pc->rq;
struct req_iterator iter; struct req_iterator iter;
struct bio_vec *bvec; struct bio_vec *bvec;
@ -246,9 +247,9 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
data = bvec_kmap_irq(bvec, &flags); data = bvec_kmap_irq(bvec, &flags);
if (direction) if (direction)
drive->hwif->atapi_output_bytes(drive, data, count); hwif->output_data(drive, NULL, data, count);
else else
drive->hwif->atapi_input_bytes(drive, data, count); hwif->input_data(drive, NULL, data, count);
bvec_kunmap_irq(data, &flags); bvec_kunmap_irq(data, &flags);
bcount -= count; bcount -= count;
@ -261,10 +262,7 @@ static void ide_floppy_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
if (bcount) { if (bcount) {
printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n", printk(KERN_ERR "%s: leftover data in %s, bcount == %d\n",
drive->name, __func__, bcount); drive->name, __func__, bcount);
if (direction) ide_pad_transfer(drive, direction, bcount);
ide_atapi_write_zeros(drive, bcount);
else
ide_atapi_discard_data(drive, bcount);
} }
} }
@ -490,7 +488,7 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
printk(KERN_ERR "ide-floppy: The floppy wants " printk(KERN_ERR "ide-floppy: The floppy wants "
"to send us more data than expected " "to send us more data than expected "
"- discarding data\n"); "- discarding data\n");
ide_atapi_discard_data(drive, bcount); ide_pad_transfer(drive, 0, bcount);
ide_set_handler(drive, ide_set_handler(drive,
&idefloppy_pc_intr, &idefloppy_pc_intr,
@ -503,12 +501,12 @@ static ide_startstop_t idefloppy_pc_intr(ide_drive_t *drive)
} }
} }
if (pc->flags & PC_FLAG_WRITING) if (pc->flags & PC_FLAG_WRITING)
xferfunc = hwif->atapi_output_bytes; xferfunc = hwif->output_data;
else else
xferfunc = hwif->atapi_input_bytes; xferfunc = hwif->input_data;
if (pc->buf) if (pc->buf)
xferfunc(drive, pc->cur_pos, bcount); xferfunc(drive, NULL, pc->cur_pos, bcount);
else else
ide_floppy_io_buffers(drive, pc, bcount, ide_floppy_io_buffers(drive, pc, bcount,
!!(pc->flags & PC_FLAG_WRITING)); !!(pc->flags & PC_FLAG_WRITING));
@ -548,8 +546,10 @@ static ide_startstop_t idefloppy_transfer_pc(ide_drive_t *drive)
/* Set the interrupt routine */ /* Set the interrupt routine */
ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); ide_set_handler(drive, &idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL);
/* Send the actual packet */ /* Send the actual packet */
HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12); hwif->output_data(drive, NULL, floppy->pc->c, 12);
return ide_started; return ide_started;
} }
@ -569,7 +569,8 @@ static int idefloppy_transfer_pc2(ide_drive_t *drive)
idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_floppy_t *floppy = drive->driver_data;
/* Send the actual packet */ /* Send the actual packet */
HWIF(drive)->atapi_output_bytes(drive, floppy->pc->c, 12); drive->hwif->output_data(drive, NULL, floppy->pc->c, 12);
/* Timeout for the packet command */ /* Timeout for the packet command */
return IDEFLOPPY_WAIT_CMD; return IDEFLOPPY_WAIT_CMD;
} }
@ -692,7 +693,7 @@ static ide_startstop_t idefloppy_issue_pc(ide_drive_t *drive,
return ide_started; return ide_started;
} else { } else {
/* Issue the packet command */ /* Issue the packet command */
hwif->OUTB(WIN_PACKETCMD, hwif->io_ports.command_addr); ide_execute_pkt_cmd(drive);
return (*pkt_xfer_routine) (drive); return (*pkt_xfer_routine) (drive);
} }
} }

View file

@ -295,49 +295,6 @@ static void ide_complete_pm_request (ide_drive_t *drive, struct request *rq)
spin_unlock_irqrestore(&ide_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
} }
void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
struct ide_taskfile *tf = &task->tf;
if (task->tf_flags & IDE_TFLAG_IN_DATA) {
u16 data = hwif->INW(io_ports->data_addr);
tf->data = data & 0xff;
tf->hob_data = (data >> 8) & 0xff;
}
/* be sure we're looking at the low order bits */
hwif->OUTB(drive->ctl & ~0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = hwif->INB(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
tf->lbal = hwif->INB(io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAM)
tf->lbam = hwif->INB(io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAH)
tf->lbah = hwif->INB(io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
tf->device = hwif->INB(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
hwif->OUTB(drive->ctl | 0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = hwif->INB(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
tf->hob_nsect = hwif->INB(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
tf->hob_lbal = hwif->INB(io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
tf->hob_lbam = hwif->INB(io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
tf->hob_lbah = hwif->INB(io_ports->lbah_addr);
}
}
/** /**
* ide_end_drive_cmd - end an explicit drive command * ide_end_drive_cmd - end an explicit drive command
* @drive: command * @drive: command
@ -373,7 +330,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err)
tf->error = err; tf->error = err;
tf->status = stat; tf->status = stat;
ide_tf_read(drive, task); drive->hwif->tf_read(drive, task);
if (task->tf_flags & IDE_TFLAG_DYN) if (task->tf_flags & IDE_TFLAG_DYN)
kfree(task); kfree(task);
@ -422,7 +379,7 @@ static void try_to_flush_leftover_data (ide_drive_t *drive)
u32 wcount = (i > 16) ? 16 : i; u32 wcount = (i > 16) ? 16 : i;
i -= wcount; i -= wcount;
HWIF(drive)->ata_input_data(drive, buffer, wcount); drive->hwif->input_data(drive, NULL, buffer, wcount * 4);
} }
} }
@ -502,7 +459,8 @@ static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u
if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT)) if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
/* force an abort */ /* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE, hwif->io_ports.command_addr); hwif->OUTBSYNC(drive, WIN_IDLEIMMEDIATE,
hwif->io_ports.command_addr);
if (rq->errors >= ERROR_MAX) { if (rq->errors >= ERROR_MAX) {
ide_kill_rq(drive, rq); ide_kill_rq(drive, rq);
@ -1679,7 +1637,23 @@ void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma)
task.tf.lbam = bcount & 0xff; task.tf.lbam = bcount & 0xff;
task.tf.lbah = (bcount >> 8) & 0xff; task.tf.lbah = (bcount >> 8) & 0xff;
ide_tf_load(drive, &task); ide_tf_dump(drive->name, &task.tf);
drive->hwif->tf_load(drive, &task);
} }
EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load); EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load);
void ide_pad_transfer(ide_drive_t *drive, int write, int len)
{
ide_hwif_t *hwif = drive->hwif;
u8 buf[4] = { 0 };
while (len > 0) {
if (write)
hwif->output_data(drive, NULL, buf, min(4, len));
else
hwif->input_data(drive, NULL, buf, min(4, len));
len -= 4;
}
}
EXPORT_SYMBOL_GPL(ide_pad_transfer);

View file

@ -37,21 +37,6 @@ static u8 ide_inb (unsigned long port)
return (u8) inb(port); return (u8) inb(port);
} }
static u16 ide_inw (unsigned long port)
{
return (u16) inw(port);
}
static void ide_insw (unsigned long port, void *addr, u32 count)
{
insw(port, addr, count);
}
static void ide_insl (unsigned long port, void *addr, u32 count)
{
insl(port, addr, count);
}
static void ide_outb (u8 val, unsigned long port) static void ide_outb (u8 val, unsigned long port)
{ {
outb(val, port); outb(val, port);
@ -62,32 +47,11 @@ static void ide_outbsync (ide_drive_t *drive, u8 addr, unsigned long port)
outb(addr, port); outb(addr, port);
} }
static void ide_outw (u16 val, unsigned long port)
{
outw(val, port);
}
static void ide_outsw (unsigned long port, void *addr, u32 count)
{
outsw(port, addr, count);
}
static void ide_outsl (unsigned long port, void *addr, u32 count)
{
outsl(port, addr, count);
}
void default_hwif_iops (ide_hwif_t *hwif) void default_hwif_iops (ide_hwif_t *hwif)
{ {
hwif->OUTB = ide_outb; hwif->OUTB = ide_outb;
hwif->OUTBSYNC = ide_outbsync; hwif->OUTBSYNC = ide_outbsync;
hwif->OUTW = ide_outw;
hwif->OUTSW = ide_outsw;
hwif->OUTSL = ide_outsl;
hwif->INB = ide_inb; hwif->INB = ide_inb;
hwif->INW = ide_inw;
hwif->INSW = ide_insw;
hwif->INSL = ide_insl;
} }
/* /*
@ -99,21 +63,6 @@ static u8 ide_mm_inb (unsigned long port)
return (u8) readb((void __iomem *) port); return (u8) readb((void __iomem *) port);
} }
static u16 ide_mm_inw (unsigned long port)
{
return (u16) readw((void __iomem *) port);
}
static void ide_mm_insw (unsigned long port, void *addr, u32 count)
{
__ide_mm_insw((void __iomem *) port, addr, count);
}
static void ide_mm_insl (unsigned long port, void *addr, u32 count)
{
__ide_mm_insl((void __iomem *) port, addr, count);
}
static void ide_mm_outb (u8 value, unsigned long port) static void ide_mm_outb (u8 value, unsigned long port)
{ {
writeb(value, (void __iomem *) port); writeb(value, (void __iomem *) port);
@ -124,34 +73,13 @@ static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port)
writeb(value, (void __iomem *) port); writeb(value, (void __iomem *) port);
} }
static void ide_mm_outw (u16 value, unsigned long port)
{
writew(value, (void __iomem *) port);
}
static void ide_mm_outsw (unsigned long port, void *addr, u32 count)
{
__ide_mm_outsw((void __iomem *) port, addr, count);
}
static void ide_mm_outsl (unsigned long port, void *addr, u32 count)
{
__ide_mm_outsl((void __iomem *) port, addr, count);
}
void default_hwif_mmiops (ide_hwif_t *hwif) void default_hwif_mmiops (ide_hwif_t *hwif)
{ {
hwif->OUTB = ide_mm_outb; hwif->OUTB = ide_mm_outb;
/* Most systems will need to override OUTBSYNC, alas however /* Most systems will need to override OUTBSYNC, alas however
this one is controller specific! */ this one is controller specific! */
hwif->OUTBSYNC = ide_mm_outbsync; hwif->OUTBSYNC = ide_mm_outbsync;
hwif->OUTW = ide_mm_outw;
hwif->OUTSW = ide_mm_outsw;
hwif->OUTSL = ide_mm_outsl;
hwif->INB = ide_mm_inb; hwif->INB = ide_mm_inb;
hwif->INW = ide_mm_inw;
hwif->INSW = ide_mm_insw;
hwif->INSL = ide_mm_insl;
} }
EXPORT_SYMBOL(default_hwif_mmiops); EXPORT_SYMBOL(default_hwif_mmiops);
@ -175,6 +103,123 @@ void SELECT_MASK (ide_drive_t *drive, int mask)
port_ops->maskproc(drive, mask); port_ops->maskproc(drive, mask);
} }
static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
struct ide_taskfile *tf = &task->tf;
void (*tf_outb)(u8 addr, unsigned long port);
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
if (mmio)
tf_outb = ide_mm_outb;
else
tf_outb = ide_outb;
if (task->tf_flags & IDE_TFLAG_FLAGGED)
HIHI = 0xFF;
ide_set_irq(drive, 1);
if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
SELECT_MASK(drive, 0);
if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
u16 data = (tf->hob_data << 8) | tf->data;
if (mmio)
writew(data, (void __iomem *)io_ports->data_addr);
else
outw(data, io_ports->data_addr);
}
if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
tf_outb(tf->hob_feature, io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
tf_outb(tf->hob_nsect, io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
tf_outb(tf->hob_lbal, io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
tf_outb(tf->hob_lbam, io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
tf_outb(tf->hob_lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
tf_outb(tf->feature, io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
tf_outb(tf->nsect, io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
tf_outb(tf->lbal, io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
tf_outb(tf->lbam, io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
tf_outb(tf->lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
tf_outb((tf->device & HIHI) | drive->select.all,
io_ports->device_addr);
}
static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
{
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
struct ide_taskfile *tf = &task->tf;
void (*tf_outb)(u8 addr, unsigned long port);
u8 (*tf_inb)(unsigned long port);
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
if (mmio) {
tf_outb = ide_mm_outb;
tf_inb = ide_mm_inb;
} else {
tf_outb = ide_outb;
tf_inb = ide_inb;
}
if (task->tf_flags & IDE_TFLAG_IN_DATA) {
u16 data;
if (mmio)
data = readw((void __iomem *)io_ports->data_addr);
else
data = inw(io_ports->data_addr);
tf->data = data & 0xff;
tf->hob_data = (data >> 8) & 0xff;
}
/* be sure we're looking at the low order bits */
tf_outb(drive->ctl & ~0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = tf_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
tf->lbal = tf_inb(io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAM)
tf->lbam = tf_inb(io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAH)
tf->lbah = tf_inb(io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
tf->device = tf_inb(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
tf_outb(drive->ctl | 0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = tf_inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
tf->hob_nsect = tf_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
tf->hob_lbal = tf_inb(io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
tf->hob_lbam = tf_inb(io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
tf->hob_lbah = tf_inb(io_ports->lbah_addr);
}
}
/* /*
* Some localbus EIDE interfaces require a special access sequence * Some localbus EIDE interfaces require a special access sequence
* when using 32-bit I/O instructions to transfer data. We call this * when using 32-bit I/O instructions to transfer data. We call this
@ -182,109 +227,112 @@ void SELECT_MASK (ide_drive_t *drive, int mask)
* of the sector count register location, with interrupts disabled * of the sector count register location, with interrupts disabled
* to ensure that the reads all happen together. * to ensure that the reads all happen together.
*/ */
static void ata_vlb_sync(ide_drive_t *drive, unsigned long port) static void ata_vlb_sync(unsigned long port)
{ {
(void) HWIF(drive)->INB(port); (void)inb(port);
(void) HWIF(drive)->INB(port); (void)inb(port);
(void) HWIF(drive)->INB(port); (void)inb(port);
} }
/* /*
* This is used for most PIO data transfers *from* the IDE interface * This is used for most PIO data transfers *from* the IDE interface
*
* These routines will round up any request for an odd number of bytes,
* so if an odd len is specified, be sure that there's at least one
* extra byte allocated for the buffer.
*/ */
static void ata_input_data(ide_drive_t *drive, void *buffer, u32 wcount) static void ata_input_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports; struct ide_io_ports *io_ports = &hwif->io_ports;
unsigned long data_addr = io_ports->data_addr;
u8 io_32bit = drive->io_32bit; u8 io_32bit = drive->io_32bit;
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
len++;
if (io_32bit) { if (io_32bit) {
if (io_32bit & 2) { unsigned long uninitialized_var(flags);
unsigned long flags;
if ((io_32bit & 2) && !mmio) {
local_irq_save(flags); local_irq_save(flags);
ata_vlb_sync(drive, io_ports->nsect_addr); ata_vlb_sync(io_ports->nsect_addr);
hwif->INSL(io_ports->data_addr, buffer, wcount); }
if (mmio)
__ide_mm_insl((void __iomem *)data_addr, buf, len / 4);
else
insl(data_addr, buf, len / 4);
if ((io_32bit & 2) && !mmio)
local_irq_restore(flags); local_irq_restore(flags);
} else
hwif->INSL(io_ports->data_addr, buffer, wcount); if ((len & 3) >= 2) {
} else if (mmio)
hwif->INSW(io_ports->data_addr, buffer, wcount << 1); __ide_mm_insw((void __iomem *)data_addr,
(u8 *)buf + (len & ~3), 1);
else
insw(data_addr, (u8 *)buf + (len & ~3), 1);
}
} else {
if (mmio)
__ide_mm_insw((void __iomem *)data_addr, buf, len / 2);
else
insw(data_addr, buf, len / 2);
}
} }
/* /*
* This is used for most PIO data transfers *to* the IDE interface * This is used for most PIO data transfers *to* the IDE interface
*/ */
static void ata_output_data(ide_drive_t *drive, void *buffer, u32 wcount) static void ata_output_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports; struct ide_io_ports *io_ports = &hwif->io_ports;
unsigned long data_addr = io_ports->data_addr;
u8 io_32bit = drive->io_32bit; u8 io_32bit = drive->io_32bit;
u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0;
if (io_32bit) { if (io_32bit) {
if (io_32bit & 2) { unsigned long uninitialized_var(flags);
unsigned long flags;
if ((io_32bit & 2) && !mmio) {
local_irq_save(flags); local_irq_save(flags);
ata_vlb_sync(drive, io_ports->nsect_addr); ata_vlb_sync(io_ports->nsect_addr);
hwif->OUTSL(io_ports->data_addr, buffer, wcount); }
if (mmio)
__ide_mm_outsl((void __iomem *)data_addr, buf, len / 4);
else
outsl(data_addr, buf, len / 4);
if ((io_32bit & 2) && !mmio)
local_irq_restore(flags); local_irq_restore(flags);
} else
hwif->OUTSL(io_ports->data_addr, buffer, wcount);
} else
hwif->OUTSW(io_ports->data_addr, buffer, wcount << 1);
}
/* if ((len & 3) >= 2) {
* The following routines are mainly used by the ATAPI drivers. if (mmio)
* __ide_mm_outsw((void __iomem *)data_addr,
* These routines will round up any request for an odd number of bytes, (u8 *)buf + (len & ~3), 1);
* so if an odd bytecount is specified, be sure that there's at least one else
* extra byte allocated for the buffer. outsw(data_addr, (u8 *)buf + (len & ~3), 1);
*/ }
} else {
static void atapi_input_bytes(ide_drive_t *drive, void *buffer, u32 bytecount) if (mmio)
{ __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2);
ide_hwif_t *hwif = HWIF(drive); else
outsw(data_addr, buf, len / 2);
++bytecount;
#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
if (MACH_IS_ATARI || MACH_IS_Q40) {
/* Atari has a byte-swapped IDE interface */
insw_swapw(hwif->io_ports.data_addr, buffer, bytecount / 2);
return;
} }
#endif /* CONFIG_ATARI || CONFIG_Q40 */
hwif->ata_input_data(drive, buffer, bytecount / 4);
if ((bytecount & 0x03) >= 2)
hwif->INSW(hwif->io_ports.data_addr,
(u8 *)buffer + (bytecount & ~0x03), 1);
}
static void atapi_output_bytes(ide_drive_t *drive, void *buffer, u32 bytecount)
{
ide_hwif_t *hwif = HWIF(drive);
++bytecount;
#if defined(CONFIG_ATARI) || defined(CONFIG_Q40)
if (MACH_IS_ATARI || MACH_IS_Q40) {
/* Atari has a byte-swapped IDE interface */
outsw_swapw(hwif->io_ports.data_addr, buffer, bytecount / 2);
return;
}
#endif /* CONFIG_ATARI || CONFIG_Q40 */
hwif->ata_output_data(drive, buffer, bytecount / 4);
if ((bytecount & 0x03) >= 2)
hwif->OUTSW(hwif->io_ports.data_addr,
(u8 *)buffer + (bytecount & ~0x03), 1);
} }
void default_hwif_transport(ide_hwif_t *hwif) void default_hwif_transport(ide_hwif_t *hwif)
{ {
hwif->ata_input_data = ata_input_data; hwif->tf_load = ide_tf_load;
hwif->ata_output_data = ata_output_data; hwif->tf_read = ide_tf_read;
hwif->atapi_input_bytes = atapi_input_bytes;
hwif->atapi_output_bytes = atapi_output_bytes; hwif->input_data = ata_input_data;
hwif->output_data = ata_output_data;
} }
void ide_fix_driveid (struct hd_driveid *id) void ide_fix_driveid (struct hd_driveid *id)
@ -577,6 +625,8 @@ static const struct drive_list_entry ivb_list[] = {
{ "TSSTcorp CDDVDW SH-S202J" , "SB01" }, { "TSSTcorp CDDVDW SH-S202J" , "SB01" },
{ "TSSTcorp CDDVDW SH-S202N" , "SB00" }, { "TSSTcorp CDDVDW SH-S202N" , "SB00" },
{ "TSSTcorp CDDVDW SH-S202N" , "SB01" }, { "TSSTcorp CDDVDW SH-S202N" , "SB01" },
{ "TSSTcorp CDDVDW SH-S202H" , "SB00" },
{ "TSSTcorp CDDVDW SH-S202H" , "SB01" },
{ NULL , NULL } { NULL , NULL }
}; };
@ -641,7 +691,7 @@ int ide_driveid_update(ide_drive_t *drive)
SELECT_MASK(drive, 1); SELECT_MASK(drive, 1);
ide_set_irq(drive, 1); ide_set_irq(drive, 1);
msleep(50); msleep(50);
hwif->OUTB(WIN_IDENTIFY, hwif->io_ports.command_addr); hwif->OUTBSYNC(drive, WIN_IDENTIFY, hwif->io_ports.command_addr);
timeout = jiffies + WAIT_WORSTCASE; timeout = jiffies + WAIT_WORSTCASE;
do { do {
if (time_after(jiffies, timeout)) { if (time_after(jiffies, timeout)) {
@ -668,7 +718,7 @@ int ide_driveid_update(ide_drive_t *drive)
local_irq_restore(flags); local_irq_restore(flags);
return 0; return 0;
} }
hwif->ata_input_data(drive, id, SECTOR_WORDS); hwif->input_data(drive, NULL, id, SECTOR_SIZE);
(void)ide_read_status(drive); /* clear drive IRQ */ (void)ide_read_status(drive); /* clear drive IRQ */
local_irq_enable(); local_irq_enable();
local_irq_restore(flags); local_irq_restore(flags);
@ -849,9 +899,19 @@ void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
ndelay(400); ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags); spin_unlock_irqrestore(&ide_lock, flags);
} }
EXPORT_SYMBOL(ide_execute_command); EXPORT_SYMBOL(ide_execute_command);
void ide_execute_pkt_cmd(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
hwif->OUTBSYNC(drive, WIN_PACKETCMD, hwif->io_ports.command_addr);
ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags);
}
EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
/* needed below */ /* needed below */
static ide_startstop_t do_reset1 (ide_drive_t *, int); static ide_startstop_t do_reset1 (ide_drive_t *, int);

View file

@ -487,7 +487,7 @@ static void ide_dump_sector(ide_drive_t *drive)
else else
task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE; task.tf_flags = IDE_TFLAG_IN_LBA | IDE_TFLAG_IN_DEVICE;
ide_tf_read(drive, &task); drive->hwif->tf_read(drive, &task);
if (lba48 || (tf->device & ATA_LBA)) if (lba48 || (tf->device & ATA_LBA))
printk(", LBAsect=%llu", printk(", LBAsect=%llu",

View file

@ -124,7 +124,7 @@ static inline void do_identify (ide_drive_t *drive, u8 cmd)
id = drive->id; id = drive->id;
/* read 512 bytes of id info */ /* read 512 bytes of id info */
hwif->ata_input_data(drive, id, SECTOR_WORDS); hwif->input_data(drive, NULL, id, SECTOR_SIZE);
drive->id_read = 1; drive->id_read = 1;
local_irq_enable(); local_irq_enable();
@ -293,7 +293,7 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd)
hwif->OUTB(0, io_ports->feature_addr); hwif->OUTB(0, io_ports->feature_addr);
/* ask drive for ID */ /* ask drive for ID */
hwif->OUTB(cmd, io_ports->command_addr); hwif->OUTBSYNC(drive, cmd, io_ports->command_addr);
timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2; timeout = ((cmd == WIN_IDENTIFY) ? WAIT_WORSTCASE : WAIT_PIDENTIFY) / 2;
timeout += jiffies; timeout += jiffies;
@ -480,7 +480,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd)
msleep(50); msleep(50);
hwif->OUTB(drive->select.all, io_ports->device_addr); hwif->OUTB(drive->select.all, io_ports->device_addr);
msleep(50); msleep(50);
hwif->OUTB(WIN_SRST, io_ports->command_addr); hwif->OUTBSYNC(drive, WIN_SRST, io_ports->command_addr);
(void)ide_busy_sleep(hwif); (void)ide_busy_sleep(hwif);
rc = try_to_identify(drive, cmd); rc = try_to_identify(drive, cmd);
} }
@ -516,7 +516,7 @@ static void enable_nest (ide_drive_t *drive)
printk("%s: enabling %s -- ", hwif->name, drive->id->model); printk("%s: enabling %s -- ", hwif->name, drive->id->model);
SELECT_DRIVE(drive); SELECT_DRIVE(drive);
msleep(50); msleep(50);
hwif->OUTB(EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr); hwif->OUTBSYNC(drive, EXABYTE_ENABLE_NEST, hwif->io_ports.command_addr);
if (ide_busy_sleep(hwif)) { if (ide_busy_sleep(hwif)) {
printk(KERN_CONT "failed (timeout)\n"); printk(KERN_CONT "failed (timeout)\n");

View file

@ -395,13 +395,13 @@ static void idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
if (bh == NULL) { if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in " printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_input_buffers\n"); "idetape_input_buffers\n");
ide_atapi_discard_data(drive, bcount); ide_pad_transfer(drive, 0, bcount);
return; return;
} }
count = min( count = min(
(unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)(bh->b_size - atomic_read(&bh->b_count)),
bcount); bcount);
HWIF(drive)->atapi_input_bytes(drive, bh->b_data + drive->hwif->input_data(drive, NULL, bh->b_data +
atomic_read(&bh->b_count), count); atomic_read(&bh->b_count), count);
bcount -= count; bcount -= count;
atomic_add(count, &bh->b_count); atomic_add(count, &bh->b_count);
@ -427,7 +427,7 @@ static void idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
return; return;
} }
count = min((unsigned int)pc->b_count, (unsigned int)bcount); count = min((unsigned int)pc->b_count, (unsigned int)bcount);
HWIF(drive)->atapi_output_bytes(drive, pc->b_data, count); drive->hwif->output_data(drive, NULL, pc->b_data, count);
bcount -= count; bcount -= count;
pc->b_data += count; pc->b_data += count;
pc->b_count -= count; pc->b_count -= count;
@ -871,7 +871,7 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
printk(KERN_ERR "ide-tape: The tape wants to " printk(KERN_ERR "ide-tape: The tape wants to "
"send us more data than expected " "send us more data than expected "
"- discarding data\n"); "- discarding data\n");
ide_atapi_discard_data(drive, bcount); ide_pad_transfer(drive, 0, bcount);
ide_set_handler(drive, &idetape_pc_intr, ide_set_handler(drive, &idetape_pc_intr,
IDETAPE_WAIT_CMD, NULL); IDETAPE_WAIT_CMD, NULL);
return ide_started; return ide_started;
@ -880,16 +880,16 @@ static ide_startstop_t idetape_pc_intr(ide_drive_t *drive)
"data than expected - allowing transfer\n"); "data than expected - allowing transfer\n");
} }
iobuf = &idetape_input_buffers; iobuf = &idetape_input_buffers;
xferfunc = hwif->atapi_input_bytes; xferfunc = hwif->input_data;
} else { } else {
iobuf = &idetape_output_buffers; iobuf = &idetape_output_buffers;
xferfunc = hwif->atapi_output_bytes; xferfunc = hwif->output_data;
} }
if (pc->bh) if (pc->bh)
iobuf(drive, pc, bcount); iobuf(drive, pc, bcount);
else else
xferfunc(drive, pc->cur_pos, bcount); xferfunc(drive, NULL, pc->cur_pos, bcount);
/* Update the current position */ /* Update the current position */
pc->xferred += bcount; pc->xferred += bcount;
@ -979,7 +979,8 @@ static ide_startstop_t idetape_transfer_pc(ide_drive_t *drive)
hwif->dma_ops->dma_start(drive); hwif->dma_ops->dma_start(drive);
#endif #endif
/* Send the actual packet */ /* Send the actual packet */
HWIF(drive)->atapi_output_bytes(drive, pc->c, 12); hwif->output_data(drive, NULL, pc->c, 12);
return ide_started; return ide_started;
} }
@ -1055,7 +1056,7 @@ static ide_startstop_t idetape_issue_pc(ide_drive_t *drive,
IDETAPE_WAIT_CMD, NULL); IDETAPE_WAIT_CMD, NULL);
return ide_started; return ide_started;
} else { } else {
hwif->OUTB(WIN_PACKETCMD, hwif->io_ports.command_addr); ide_execute_pkt_cmd(drive);
return idetape_transfer_pc(drive); return idetape_transfer_pc(drive);
} }
} }

View file

@ -33,60 +33,18 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/io.h> #include <asm/io.h>
void ide_tf_load(ide_drive_t *drive, ide_task_t *task) void ide_tf_dump(const char *s, struct ide_taskfile *tf)
{ {
ide_hwif_t *hwif = drive->hwif;
struct ide_io_ports *io_ports = &hwif->io_ports;
struct ide_taskfile *tf = &task->tf;
u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
if (task->tf_flags & IDE_TFLAG_FLAGGED)
HIHI = 0xFF;
#ifdef DEBUG #ifdef DEBUG
printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x " printk("%s: tf: feat 0x%02x nsect 0x%02x lbal 0x%02x "
"lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n", "lbam 0x%02x lbah 0x%02x dev 0x%02x cmd 0x%02x\n",
drive->name, tf->feature, tf->nsect, tf->lbal, s, tf->feature, tf->nsect, tf->lbal,
tf->lbam, tf->lbah, tf->device, tf->command); tf->lbam, tf->lbah, tf->device, tf->command);
printk("%s: hob: nsect 0x%02x lbal 0x%02x " printk("%s: hob: nsect 0x%02x lbal 0x%02x "
"lbam 0x%02x lbah 0x%02x\n", "lbam 0x%02x lbah 0x%02x\n",
drive->name, tf->hob_nsect, tf->hob_lbal, s, tf->hob_nsect, tf->hob_lbal,
tf->hob_lbam, tf->hob_lbah); tf->hob_lbam, tf->hob_lbah);
#endif #endif
ide_set_irq(drive, 1);
if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
SELECT_MASK(drive, 0);
if (task->tf_flags & IDE_TFLAG_OUT_DATA)
hwif->OUTW((tf->hob_data << 8) | tf->data, io_ports->data_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
hwif->OUTB(tf->hob_feature, io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
hwif->OUTB(tf->hob_nsect, io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
hwif->OUTB(tf->hob_lbal, io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
hwif->OUTB(tf->hob_lbam, io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
hwif->OUTB(tf->hob_lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
hwif->OUTB(tf->feature, io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
hwif->OUTB(tf->nsect, io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
hwif->OUTB(tf->lbal, io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
hwif->OUTB(tf->lbam, io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
hwif->OUTB(tf->lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
hwif->OUTB((tf->device & HIHI) | drive->select.all,
io_ports->device_addr);
} }
int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf) int taskfile_lib_get_identify (ide_drive_t *drive, u8 *buf)
@ -149,8 +107,10 @@ ide_startstop_t do_rw_taskfile (ide_drive_t *drive, ide_task_t *task)
if (task->tf_flags & IDE_TFLAG_FLAGGED) if (task->tf_flags & IDE_TFLAG_FLAGGED)
task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS; task->tf_flags |= IDE_TFLAG_FLAGGED_SET_IN_FLAGS;
if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) if ((task->tf_flags & IDE_TFLAG_DMA_PIO_FALLBACK) == 0) {
ide_tf_load(drive, task); ide_tf_dump(drive->name, tf);
hwif->tf_load(drive, task);
}
switch (task->data_phase) { switch (task->data_phase) {
case TASKFILE_MULTI_OUT: case TASKFILE_MULTI_OUT:
@ -283,7 +243,8 @@ static u8 wait_drive_not_busy(ide_drive_t *drive)
return stat; return stat;
} }
static void ide_pio_sector(ide_drive_t *drive, unsigned int write) static void ide_pio_sector(ide_drive_t *drive, struct request *rq,
unsigned int write)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct scatterlist *sg = hwif->sg_table; struct scatterlist *sg = hwif->sg_table;
@ -323,9 +284,9 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
/* do the actual data transfer */ /* do the actual data transfer */
if (write) if (write)
hwif->ata_output_data(drive, buf, SECTOR_WORDS); hwif->output_data(drive, rq, buf, SECTOR_SIZE);
else else
hwif->ata_input_data(drive, buf, SECTOR_WORDS); hwif->input_data(drive, rq, buf, SECTOR_SIZE);
kunmap_atomic(buf, KM_BIO_SRC_IRQ); kunmap_atomic(buf, KM_BIO_SRC_IRQ);
#ifdef CONFIG_HIGHMEM #ifdef CONFIG_HIGHMEM
@ -333,13 +294,14 @@ static void ide_pio_sector(ide_drive_t *drive, unsigned int write)
#endif #endif
} }
static void ide_pio_multi(ide_drive_t *drive, unsigned int write) static void ide_pio_multi(ide_drive_t *drive, struct request *rq,
unsigned int write)
{ {
unsigned int nsect; unsigned int nsect;
nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count); nsect = min_t(unsigned int, drive->hwif->nleft, drive->mult_count);
while (nsect--) while (nsect--)
ide_pio_sector(drive, write); ide_pio_sector(drive, rq, write);
} }
static void ide_pio_datablock(ide_drive_t *drive, struct request *rq, static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
@ -362,10 +324,10 @@ static void ide_pio_datablock(ide_drive_t *drive, struct request *rq,
switch (drive->hwif->data_phase) { switch (drive->hwif->data_phase) {
case TASKFILE_MULTI_IN: case TASKFILE_MULTI_IN:
case TASKFILE_MULTI_OUT: case TASKFILE_MULTI_OUT:
ide_pio_multi(drive, write); ide_pio_multi(drive, rq, write);
break; break;
default: default:
ide_pio_sector(drive, write); ide_pio_sector(drive, rq, write);
break; break;
} }

View file

@ -44,6 +44,28 @@
int falconide_intr_lock; int falconide_intr_lock;
EXPORT_SYMBOL(falconide_intr_lock); EXPORT_SYMBOL(falconide_intr_lock);
static void falconide_input_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{
unsigned long data_addr = drive->hwif->io_ports.data_addr;
if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
return insw(data_addr, buf, (len + 1) / 2);
insw_swapw(data_addr, buf, (len + 1) / 2);
}
static void falconide_output_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{
unsigned long data_addr = drive->hwif->io_ports.data_addr;
if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
return outsw(data_adr, buf, (len + 1) / 2);
outsw_swapw(data_addr, buf, (len + 1) / 2);
}
static void __init falconide_setup_ports(hw_regs_t *hw) static void __init falconide_setup_ports(hw_regs_t *hw)
{ {
int i; int i;
@ -90,6 +112,10 @@ static int __init falconide_init(void)
ide_init_port_data(hwif, index); ide_init_port_data(hwif, index);
ide_init_port_hw(hwif, &hw); ide_init_port_hw(hwif, &hw);
/* Atari has a byte-swapped IDE interface */
hwif->input_data = falconide_input_data;
hwif->output_data = falconide_output_data;
ide_get_lock(NULL, NULL); ide_get_lock(NULL, NULL);
ide_device_add(idx, NULL); ide_device_add(idx, NULL);
ide_release_lock(); ide_release_lock();

View file

@ -101,8 +101,10 @@ static int __devinit plat_ide_probe(struct platform_device *pdev)
ide_init_port_hw(hwif, &hw); ide_init_port_hw(hwif, &hw);
if (mmio) if (mmio) {
hwif->host_flags = IDE_HFLAG_MMIO;
default_hwif_mmiops(hwif); default_hwif_mmiops(hwif);
}
idx[0] = hwif->index; idx[0] = hwif->index;

View file

@ -72,7 +72,27 @@ static void q40_ide_setup_ports(hw_regs_t *hw, unsigned long base,
hw->ack_intr = ack_intr; hw->ack_intr = ack_intr;
} }
static void q40ide_input_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{
unsigned long data_addr = drive->hwif->io_ports.data_addr;
if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
return insw(data_addr, buf, (len + 1) / 2);
insw_swapw(data_addr, buf, (len + 1) / 2);
}
static void q40ide_output_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{
unsigned long data_addr = drive->hwif->io_ports.data_addr;
if (drive->media == ide_disk && rq && rq->cmd_type == REQ_TYPE_FS)
return outsw(data_addr, buf, (len + 1) / 2);
outsw_swapw(data_addr, buf, (len + 1) / 2);
}
/* /*
* the static array is needed to have the name reported in /proc/ioports, * the static array is needed to have the name reported in /proc/ioports,
@ -123,6 +143,10 @@ static int __init q40ide_init(void)
ide_init_port_data(hwif, hwif->index); ide_init_port_data(hwif, hwif->index);
ide_init_port_hw(hwif, &hw); ide_init_port_hw(hwif, &hw);
/* Q40 has a byte-swapped IDE interface */
hwif->input_data = q40ide_input_data;
hwif->output_data = q40ide_output_data;
idx[i] = hwif->index; idx[i] = hwif->index;
} }
} }

View file

@ -48,8 +48,6 @@
static _auide_hwif auide_hwif; static _auide_hwif auide_hwif;
static int auide_ddma_init(_auide_hwif *auide);
#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA)
void auide_insw(unsigned long port, void *addr, u32 count) void auide_insw(unsigned long port, void *addr, u32 count)
@ -88,6 +86,17 @@ void auide_outsw(unsigned long port, void *addr, u32 count)
ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp);
} }
static void au1xxx_input_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{
auide_insw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
static void au1xxx_output_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{
auide_outsw(drive->hwif->io_ports.data_addr, buf, (len + 1) / 2);
}
#endif #endif
static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio) static void au1xxx_set_pio_mode(ide_drive_t *drive, const u8 pio)
@ -598,8 +607,8 @@ static int au_ide_probe(struct device *dev)
*/ */
#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA
hwif->INSW = auide_insw; hwif->input_data = au1xxx_input_data;
hwif->OUTSW = auide_outsw; hwif->output_data = au1xxx_output_data;
#endif #endif
hwif->select_data = 0; /* no chipset-specific code */ hwif->select_data = 0; /* no chipset-specific code */
hwif->config_data = 0; /* no chipset-specific code */ hwif->config_data = 0; /* no chipset-specific code */

View file

@ -109,6 +109,7 @@ static int __devinit swarm_ide_probe(struct device *dev)
base = ioremap(offset, size); base = ioremap(offset, size);
/* Setup MMIO ops. */ /* Setup MMIO ops. */
hwif->host_flags = IDE_HFLAG_MMIO;
default_hwif_mmiops(hwif); default_hwif_mmiops(hwif);
hwif->chipset = ide_generic; hwif->chipset = ide_generic;

View file

@ -63,6 +63,48 @@ static u8 superio_ide_inb (unsigned long port)
return inb(port); return inb(port);
} }
static void superio_tf_read(ide_drive_t *drive, ide_task_t *task)
{
struct ide_io_ports *io_ports = &drive->hwif->io_ports;
struct ide_taskfile *tf = &task->tf;
if (task->tf_flags & IDE_TFLAG_IN_DATA) {
u16 data = inw(io_ports->data_addr);
tf->data = data & 0xff;
tf->hob_data = (data >> 8) & 0xff;
}
/* be sure we're looking at the low order bits */
outb(drive->ctl & ~0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
tf->lbal = inb(io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAM)
tf->lbam = inb(io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAH)
tf->lbah = inb(io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
tf->device = superio_ide_inb(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
outb(drive->ctl | 0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
tf->hob_nsect = inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
tf->hob_lbal = inb(io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
tf->hob_lbam = inb(io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
tf->hob_lbah = inb(io_ports->lbah_addr);
}
}
static void __devinit superio_ide_init_iops (struct hwif_s *hwif) static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
{ {
struct pci_dev *pdev = to_pci_dev(hwif->dev); struct pci_dev *pdev = to_pci_dev(hwif->dev);
@ -80,6 +122,8 @@ static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
tmp = superio_ide_inb(superio_ide_dma_status[port]); tmp = superio_ide_inb(superio_ide_dma_status[port]);
outb(tmp | 0x66, superio_ide_dma_status[port]); outb(tmp | 0x66, superio_ide_dma_status[port]);
hwif->tf_read = superio_tf_read;
/* We need to override inb to workaround a SuperIO errata */ /* We need to override inb to workaround a SuperIO errata */
hwif->INB = superio_ide_inb; hwif->INB = superio_ide_inb;
} }

View file

@ -83,8 +83,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
{ {
u8 value; u8 value;
outb(index, hwif->dma_vendor1); outb(index, hwif->dma_base + 1);
value = inb(hwif->dma_vendor3); value = inb(hwif->dma_base + 3);
DBG("index[%02X] value[%02X]\n", index, value); DBG("index[%02X] value[%02X]\n", index, value);
return value; return value;
@ -97,8 +97,8 @@ static u8 get_indexed_reg(ide_hwif_t *hwif, u8 index)
*/ */
static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value) static void set_indexed_reg(ide_hwif_t *hwif, u8 index, u8 value)
{ {
outb(index, hwif->dma_vendor1); outb(index, hwif->dma_base + 1);
outb(value, hwif->dma_vendor3); outb(value, hwif->dma_base + 3);
DBG("index[%02X] value[%02X]\n", index, value); DBG("index[%02X] value[%02X]\n", index, value);
} }

View file

@ -250,6 +250,7 @@ static const struct ich_laptop ich_laptop[] = {
{ 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */ { 0x27DF, 0x1043, 0x1267 }, /* ICH7 on Asus W5F */
{ 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */ { 0x27DF, 0x103C, 0x30A1 }, /* ICH7 on HP Compaq nc2400 */
{ 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on Acer Aspire 2023WLMi */
{ 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */
/* end marker */ /* end marker */
{ 0, } { 0, }
}; };

View file

@ -126,12 +126,6 @@ static u8 scc_ide_inb(unsigned long port)
return (u8)data; return (u8)data;
} }
static u16 scc_ide_inw(unsigned long port)
{
u32 data = in_be32((void*)port);
return (u16)data;
}
static void scc_ide_insw(unsigned long port, void *addr, u32 count) static void scc_ide_insw(unsigned long port, void *addr, u32 count)
{ {
u16 *ptr = (u16 *)addr; u16 *ptr = (u16 *)addr;
@ -154,11 +148,6 @@ static void scc_ide_outb(u8 addr, unsigned long port)
out_be32((void*)port, addr); out_be32((void*)port, addr);
} }
static void scc_ide_outw(u16 addr, unsigned long port)
{
out_be32((void*)port, addr);
}
static void static void
scc_ide_outbsync(ide_drive_t * drive, u8 addr, unsigned long port) scc_ide_outbsync(ide_drive_t * drive, u8 addr, unsigned long port)
{ {
@ -271,6 +260,20 @@ static void scc_set_dma_mode(ide_drive_t *drive, const u8 speed)
out_be32((void __iomem *)udenvt_port, reg); out_be32((void __iomem *)udenvt_port, reg);
} }
static void scc_dma_host_set(ide_drive_t *drive, int on)
{
ide_hwif_t *hwif = drive->hwif;
u8 unit = (drive->select.b.unit & 0x01);
u8 dma_stat = scc_ide_inb(hwif->dma_status);
if (on)
dma_stat |= (1 << (5 + unit));
else
dma_stat &= ~(1 << (5 + unit));
scc_ide_outb(dma_stat, hwif->dma_status);
}
/** /**
* scc_ide_dma_setup - begin a DMA phase * scc_ide_dma_setup - begin a DMA phase
* @drive: target device * @drive: target device
@ -301,7 +304,7 @@ static int scc_dma_setup(ide_drive_t *drive)
} }
/* PRD table */ /* PRD table */
out_be32((void __iomem *)hwif->dma_prdtable, hwif->dmatable_dma); out_be32((void __iomem *)(hwif->dma_base + 8), hwif->dmatable_dma);
/* specify r/w */ /* specify r/w */
out_be32((void __iomem *)hwif->dma_command, reading); out_be32((void __iomem *)hwif->dma_command, reading);
@ -315,13 +318,45 @@ static int scc_dma_setup(ide_drive_t *drive)
return 0; return 0;
} }
static void scc_dma_start(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
u8 dma_cmd = scc_ide_inb(hwif->dma_command);
/* start DMA */
scc_ide_outb(dma_cmd | 1, hwif->dma_command);
hwif->dma = 1;
wmb();
}
static int __scc_dma_end(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
u8 dma_stat, dma_cmd;
drive->waiting_for_dma = 0;
/* get DMA command mode */
dma_cmd = scc_ide_inb(hwif->dma_command);
/* stop DMA */
scc_ide_outb(dma_cmd & ~1, hwif->dma_command);
/* get DMA status */
dma_stat = scc_ide_inb(hwif->dma_status);
/* clear the INTR & ERROR bits */
scc_ide_outb(dma_stat | 6, hwif->dma_status);
/* purge DMA mappings */
ide_destroy_dmatable(drive);
/* verify good DMA status */
hwif->dma = 0;
wmb();
return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0;
}
/** /**
* scc_dma_end - Stop DMA * scc_dma_end - Stop DMA
* @drive: IDE drive * @drive: IDE drive
* *
* Check and clear INT Status register. * Check and clear INT Status register.
* Then call __ide_dma_end(). * Then call __scc_dma_end().
*/ */
static int scc_dma_end(ide_drive_t *drive) static int scc_dma_end(ide_drive_t *drive)
@ -425,7 +460,7 @@ static int scc_dma_end(ide_drive_t *drive)
break; break;
} }
dma_stat = __ide_dma_end(drive); dma_stat = __scc_dma_end(drive);
if (data_loss) if (data_loss)
dma_stat |= 2; /* emulate DMA error (to retry command) */ dma_stat |= 2; /* emulate DMA error (to retry command) */
return dma_stat; return dma_stat;
@ -618,6 +653,122 @@ static int __devinit init_setup_scc(struct pci_dev *dev,
return rc; return rc;
} }
static void scc_tf_load(ide_drive_t *drive, ide_task_t *task)
{
struct ide_io_ports *io_ports = &drive->hwif->io_ports;
struct ide_taskfile *tf = &task->tf;
u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF;
if (task->tf_flags & IDE_TFLAG_FLAGGED)
HIHI = 0xFF;
ide_set_irq(drive, 1);
if (task->tf_flags & IDE_TFLAG_OUT_DATA)
out_be32((void *)io_ports->data_addr,
(tf->hob_data << 8) | tf->data);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE)
scc_ide_outb(tf->hob_feature, io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT)
scc_ide_outb(tf->hob_nsect, io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL)
scc_ide_outb(tf->hob_lbal, io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM)
scc_ide_outb(tf->hob_lbam, io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH)
scc_ide_outb(tf->hob_lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_FEATURE)
scc_ide_outb(tf->feature, io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_OUT_NSECT)
scc_ide_outb(tf->nsect, io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAL)
scc_ide_outb(tf->lbal, io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAM)
scc_ide_outb(tf->lbam, io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_OUT_LBAH)
scc_ide_outb(tf->lbah, io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_OUT_DEVICE)
scc_ide_outb((tf->device & HIHI) | drive->select.all,
io_ports->device_addr);
}
static void scc_tf_read(ide_drive_t *drive, ide_task_t *task)
{
struct ide_io_ports *io_ports = &drive->hwif->io_ports;
struct ide_taskfile *tf = &task->tf;
if (task->tf_flags & IDE_TFLAG_IN_DATA) {
u16 data = (u16)in_be32((void *)io_ports->data_addr);
tf->data = data & 0xff;
tf->hob_data = (data >> 8) & 0xff;
}
/* be sure we're looking at the low order bits */
scc_ide_outb(drive->ctl & ~0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = scc_ide_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAL)
tf->lbal = scc_ide_inb(io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAM)
tf->lbam = scc_ide_inb(io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_IN_LBAH)
tf->lbah = scc_ide_inb(io_ports->lbah_addr);
if (task->tf_flags & IDE_TFLAG_IN_DEVICE)
tf->device = scc_ide_inb(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
scc_ide_outb(drive->ctl | 0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = scc_ide_inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT)
tf->hob_nsect = scc_ide_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL)
tf->hob_lbal = scc_ide_inb(io_ports->lbal_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM)
tf->hob_lbam = scc_ide_inb(io_ports->lbam_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH)
tf->hob_lbah = scc_ide_inb(io_ports->lbah_addr);
}
}
static void scc_input_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{
unsigned long data_addr = drive->hwif->io_ports.data_addr;
len++;
if (drive->io_32bit) {
scc_ide_insl(data_addr, buf, len / 4);
if ((len & 3) >= 2)
scc_ide_insw(data_addr, (u8 *)buf + (len & ~3), 1);
} else
scc_ide_insw(data_addr, buf, len / 2);
}
static void scc_output_data(ide_drive_t *drive, struct request *rq,
void *buf, unsigned int len)
{
unsigned long data_addr = drive->hwif->io_ports.data_addr;
len++;
if (drive->io_32bit) {
scc_ide_outsl(data_addr, buf, len / 4);
if ((len & 3) >= 2)
scc_ide_outsw(data_addr, (u8 *)buf + (len & ~3), 1);
} else
scc_ide_outsw(data_addr, buf, len / 2);
}
/** /**
* init_mmio_iops_scc - set up the iops for MMIO * init_mmio_iops_scc - set up the iops for MMIO
* @hwif: interface to set up * @hwif: interface to set up
@ -632,15 +783,15 @@ static void __devinit init_mmio_iops_scc(ide_hwif_t *hwif)
ide_set_hwifdata(hwif, ports); ide_set_hwifdata(hwif, ports);
hwif->tf_load = scc_tf_load;
hwif->tf_read = scc_tf_read;
hwif->input_data = scc_input_data;
hwif->output_data = scc_output_data;
hwif->INB = scc_ide_inb; hwif->INB = scc_ide_inb;
hwif->INW = scc_ide_inw;
hwif->INSW = scc_ide_insw;
hwif->INSL = scc_ide_insl;
hwif->OUTB = scc_ide_outb; hwif->OUTB = scc_ide_outb;
hwif->OUTBSYNC = scc_ide_outbsync; hwif->OUTBSYNC = scc_ide_outbsync;
hwif->OUTW = scc_ide_outw;
hwif->OUTSW = scc_ide_outsw;
hwif->OUTSL = scc_ide_outsl;
hwif->dma_base = dma_base; hwif->dma_base = dma_base;
hwif->config_data = ports->ctl; hwif->config_data = ports->ctl;
@ -687,7 +838,6 @@ static void __devinit init_hwif_scc(ide_hwif_t *hwif)
hwif->dma_command = hwif->dma_base; hwif->dma_command = hwif->dma_base;
hwif->dma_status = hwif->dma_base + 0x04; hwif->dma_status = hwif->dma_base + 0x04;
hwif->dma_prdtable = hwif->dma_base + 0x08;
/* PTERADD */ /* PTERADD */
out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma); out_be32((void __iomem *)(hwif->dma_base + 0x018), hwif->dmatable_dma);
@ -706,10 +856,10 @@ static const struct ide_port_ops scc_port_ops = {
}; };
static const struct ide_dma_ops scc_dma_ops = { static const struct ide_dma_ops scc_dma_ops = {
.dma_host_set = ide_dma_host_set, .dma_host_set = scc_dma_host_set,
.dma_setup = scc_dma_setup, .dma_setup = scc_dma_setup,
.dma_exec_cmd = ide_dma_exec_cmd, .dma_exec_cmd = ide_dma_exec_cmd,
.dma_start = ide_dma_start, .dma_start = scc_dma_start,
.dma_end = scc_dma_end, .dma_end = scc_dma_end,
.dma_test_irq = scc_dma_test_irq, .dma_test_irq = scc_dma_test_irq,
.dma_lost_irq = ide_dma_lost_irq, .dma_lost_irq = ide_dma_lost_irq,

View file

@ -573,6 +573,7 @@ static const struct ide_port_info sgiioc4_port_info __devinitdata = {
.init_dma = ide_dma_sgiioc4, .init_dma = ide_dma_sgiioc4,
.port_ops = &sgiioc4_port_ops, .port_ops = &sgiioc4_port_ops,
.dma_ops = &sgiioc4_dma_ops, .dma_ops = &sgiioc4_dma_ops,
.host_flags = IDE_HFLAG_MMIO,
.mwdma_mask = ATA_MWDMA2_ONLY, .mwdma_mask = ATA_MWDMA2_ONLY,
}; };

View file

@ -1,8 +1,8 @@
/* /*
* Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2003 Red Hat <alan@redhat.com> * Copyright (C) 2003 Red Hat <alan@redhat.com>
* Copyright (C) 2007 MontaVista Software, Inc. * Copyright (C) 2007-2008 MontaVista Software, Inc.
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz * Copyright (C) 2007-2008 Bartlomiej Zolnierkiewicz
* *
* May be copied or modified under the terms of the GNU General Public License * May be copied or modified under the terms of the GNU General Public License
* *
@ -17,10 +17,10 @@
* *
* FAQ Items: * FAQ Items:
* If you are using Marvell SATA-IDE adapters with Maxtor drives * If you are using Marvell SATA-IDE adapters with Maxtor drives
* ensure the system is set up for ATA100/UDMA5 not UDMA6. * ensure the system is set up for ATA100/UDMA5, not UDMA6.
* *
* If you are using WD drives with SATA bridges you must set the * If you are using WD drives with SATA bridges you must set the
* drive to "Single". "Master" will hang * drive to "Single". "Master" will hang.
* *
* If you have strange problems with nVidia chipset systems please * If you have strange problems with nVidia chipset systems please
* see the SI support documentation and update your system BIOS * see the SI support documentation and update your system BIOS
@ -42,8 +42,7 @@
#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 <linux/io.h>
#include <asm/io.h>
/** /**
* pdev_is_sata - check if device is SATA * pdev_is_sata - check if device is SATA
@ -55,12 +54,12 @@
static int pdev_is_sata(struct pci_dev *pdev) static int pdev_is_sata(struct pci_dev *pdev)
{ {
#ifdef CONFIG_BLK_DEV_IDE_SATA #ifdef CONFIG_BLK_DEV_IDE_SATA
switch(pdev->device) { switch (pdev->device) {
case PCI_DEVICE_ID_SII_3112: case PCI_DEVICE_ID_SII_3112:
case PCI_DEVICE_ID_SII_1210SA: case PCI_DEVICE_ID_SII_1210SA:
return 1; return 1;
case PCI_DEVICE_ID_SII_680: case PCI_DEVICE_ID_SII_680:
return 0; return 0;
} }
BUG(); BUG();
#endif #endif
@ -86,18 +85,19 @@ static inline int is_sata(ide_hwif_t *hwif)
* *
* Turn a config register offset into the right address in either * Turn a config register offset into the right address in either
* PCI space or MMIO space to access the control register in question * PCI space or MMIO space to access the control register in question
* Thankfully this is a configuration operation so isnt performance * Thankfully this is a configuration operation, so isn't performance
* criticial. * critical.
*/ */
static unsigned long siimage_selreg(ide_hwif_t *hwif, int r) static unsigned long siimage_selreg(ide_hwif_t *hwif, int r)
{ {
unsigned long base = (unsigned long)hwif->hwif_data; unsigned long base = (unsigned long)hwif->hwif_data;
base += 0xA0 + r; base += 0xA0 + r;
if(hwif->mmio) if (hwif->mmio)
base += (hwif->channel << 6); base += hwif->channel << 6;
else else
base += (hwif->channel << 4); base += hwif->channel << 4;
return base; return base;
} }
@ -114,16 +114,65 @@ static unsigned long siimage_selreg(ide_hwif_t *hwif, int r)
static inline unsigned long siimage_seldev(ide_drive_t *drive, int r) static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
unsigned long base = (unsigned long)hwif->hwif_data; unsigned long base = (unsigned long)hwif->hwif_data;
base += 0xA0 + r; base += 0xA0 + r;
if(hwif->mmio) if (hwif->mmio)
base += (hwif->channel << 6); base += hwif->channel << 6;
else else
base += (hwif->channel << 4); base += hwif->channel << 4;
base |= drive->select.b.unit << drive->select.b.unit; base |= drive->select.b.unit << drive->select.b.unit;
return base; return base;
} }
static u8 sil_ioread8(struct pci_dev *dev, unsigned long addr)
{
u8 tmp = 0;
if (pci_get_drvdata(dev))
tmp = readb((void __iomem *)addr);
else
pci_read_config_byte(dev, addr, &tmp);
return tmp;
}
static u16 sil_ioread16(struct pci_dev *dev, unsigned long addr)
{
u16 tmp = 0;
if (pci_get_drvdata(dev))
tmp = readw((void __iomem *)addr);
else
pci_read_config_word(dev, addr, &tmp);
return tmp;
}
static void sil_iowrite8(struct pci_dev *dev, u8 val, unsigned long addr)
{
if (pci_get_drvdata(dev))
writeb(val, (void __iomem *)addr);
else
pci_write_config_byte(dev, addr, val);
}
static void sil_iowrite16(struct pci_dev *dev, u16 val, unsigned long addr)
{
if (pci_get_drvdata(dev))
writew(val, (void __iomem *)addr);
else
pci_write_config_word(dev, addr, val);
}
static void sil_iowrite32(struct pci_dev *dev, u32 val, unsigned long addr)
{
if (pci_get_drvdata(dev))
writel(val, (void __iomem *)addr);
else
pci_write_config_dword(dev, addr, val);
}
/** /**
* sil_udma_filter - compute UDMA mask * sil_udma_filter - compute UDMA mask
* @drive: IDE device * @drive: IDE device
@ -136,24 +185,26 @@ static inline unsigned long siimage_seldev(ide_drive_t *drive, int r)
static u8 sil_pata_udma_filter(ide_drive_t *drive) static u8 sil_pata_udma_filter(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
struct pci_dev *dev = to_pci_dev(hwif->dev); struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long base = (unsigned long) hwif->hwif_data; unsigned long base = (unsigned long)hwif->hwif_data;
u8 mask = 0, scsc = 0; u8 scsc, mask = 0;
if (hwif->mmio) scsc = sil_ioread8(dev, base + (hwif->mmio ? 0x4A : 0x8A));
scsc = hwif->INB(base + 0x4A);
else
pci_read_config_byte(dev, 0x8A, &scsc);
if ((scsc & 0x30) == 0x10) /* 133 */ switch (scsc & 0x30) {
case 0x10: /* 133 */
mask = ATA_UDMA6; mask = ATA_UDMA6;
else if ((scsc & 0x30) == 0x20) /* 2xPCI */ break;
case 0x20: /* 2xPCI */
mask = ATA_UDMA6; mask = ATA_UDMA6;
else if ((scsc & 0x30) == 0x00) /* 100 */ break;
case 0x00: /* 100 */
mask = ATA_UDMA5; mask = ATA_UDMA5;
else /* Disabled ? */ break;
default: /* Disabled ? */
BUG(); BUG();
}
return mask; return mask;
} }
@ -175,15 +226,16 @@ static u8 sil_sata_udma_filter(ide_drive_t *drive)
static void sil_set_pio_mode(ide_drive_t *drive, u8 pio) static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
{ {
const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 }; static const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 };
const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; static const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 };
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev);
ide_drive_t *pair = ide_get_paired_drive(drive); ide_drive_t *pair = ide_get_paired_drive(drive);
u32 speedt = 0; u32 speedt = 0;
u16 speedp = 0; u16 speedp = 0;
unsigned long addr = siimage_seldev(drive, 0x04); unsigned long addr = siimage_seldev(drive, 0x04);
unsigned long tfaddr = siimage_selreg(hwif, 0x02); unsigned long tfaddr = siimage_selreg(hwif, 0x02);
unsigned long base = (unsigned long)hwif->hwif_data; unsigned long base = (unsigned long)hwif->hwif_data;
u8 tf_pio = pio; u8 tf_pio = pio;
u8 addr_mask = hwif->channel ? (hwif->mmio ? 0xF4 : 0x84) u8 addr_mask = hwif->channel ? (hwif->mmio ? 0xF4 : 0x84)
@ -203,36 +255,20 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
speedp = data_speed[pio]; speedp = data_speed[pio];
speedt = tf_speed[tf_pio]; speedt = tf_speed[tf_pio];
if (hwif->mmio) { sil_iowrite16(dev, speedp, addr);
hwif->OUTW(speedp, addr); sil_iowrite16(dev, speedt, tfaddr);
hwif->OUTW(speedt, tfaddr);
/* Now set up IORDY */
if (pio > 2)
hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2);
else
hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2);
mode = hwif->INB(base + addr_mask); /* now set up IORDY */
mode &= ~(unit ? 0x30 : 0x03); speedp = sil_ioread16(dev, tfaddr - 2);
mode |= (unit ? 0x10 : 0x01); speedp &= ~0x200;
hwif->OUTB(mode, base + addr_mask); if (pio > 2)
} else { speedp |= 0x200;
struct pci_dev *dev = to_pci_dev(hwif->dev); sil_iowrite16(dev, speedp, tfaddr - 2);
pci_write_config_word(dev, addr, speedp); mode = sil_ioread8(dev, base + addr_mask);
pci_write_config_word(dev, tfaddr, speedt); mode &= ~(unit ? 0x30 : 0x03);
pci_read_config_word(dev, tfaddr - 2, &speedp); mode |= unit ? 0x10 : 0x01;
speedp &= ~0x200; sil_iowrite8(dev, mode, base + addr_mask);
/* Set IORDY for mode 3 or 4 */
if (pio > 2)
speedp |= 0x200;
pci_write_config_word(dev, tfaddr - 2, speedp);
pci_read_config_byte(dev, addr_mask, &mode);
mode &= ~(unit ? 0x30 : 0x03);
mode |= (unit ? 0x10 : 0x01);
pci_write_config_byte(dev, addr_mask, mode);
}
} }
/** /**
@ -245,59 +281,45 @@ static void sil_set_pio_mode(ide_drive_t *drive, u8 pio)
static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed) static void sil_set_dma_mode(ide_drive_t *drive, const u8 speed)
{ {
u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 }; static const u8 ultra6[] = { 0x0F, 0x0B, 0x07, 0x05, 0x03, 0x02, 0x01 };
u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 }; static const u8 ultra5[] = { 0x0C, 0x07, 0x05, 0x04, 0x02, 0x01 };
u16 dma[] = { 0x2208, 0x10C2, 0x10C1 }; static const u16 dma[] = { 0x2208, 0x10C2, 0x10C1 };
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = to_pci_dev(hwif->dev); struct pci_dev *dev = to_pci_dev(hwif->dev);
u16 ultra = 0, multi = 0; u16 ultra = 0, multi = 0;
u8 mode = 0, unit = drive->select.b.unit; u8 mode = 0, unit = drive->select.b.unit;
unsigned long base = (unsigned long)hwif->hwif_data; unsigned long base = (unsigned long)hwif->hwif_data;
u8 scsc = 0, addr_mask = ((hwif->channel) ? u8 scsc = 0, addr_mask = hwif->channel ?
((hwif->mmio) ? 0xF4 : 0x84) : (hwif->mmio ? 0xF4 : 0x84) :
((hwif->mmio) ? 0xB4 : 0x80)); (hwif->mmio ? 0xB4 : 0x80);
unsigned long ma = siimage_seldev(drive, 0x08); unsigned long ma = siimage_seldev(drive, 0x08);
unsigned long ua = siimage_seldev(drive, 0x0C); unsigned long ua = siimage_seldev(drive, 0x0C);
if (hwif->mmio) { scsc = sil_ioread8 (dev, base + (hwif->mmio ? 0x4A : 0x8A));
scsc = hwif->INB(base + 0x4A); mode = sil_ioread8 (dev, base + addr_mask);
mode = hwif->INB(base + addr_mask); multi = sil_ioread16(dev, ma);
multi = hwif->INW(ma); ultra = sil_ioread16(dev, ua);
ultra = hwif->INW(ua);
} else {
pci_read_config_byte(dev, 0x8A, &scsc);
pci_read_config_byte(dev, addr_mask, &mode);
pci_read_config_word(dev, ma, &multi);
pci_read_config_word(dev, ua, &ultra);
}
mode &= ~((unit) ? 0x30 : 0x03); mode &= ~(unit ? 0x30 : 0x03);
ultra &= ~0x3F; ultra &= ~0x3F;
scsc = ((scsc & 0x30) == 0x00) ? 0 : 1; scsc = ((scsc & 0x30) == 0x00) ? 0 : 1;
scsc = is_sata(hwif) ? 1 : scsc; scsc = is_sata(hwif) ? 1 : scsc;
if (speed >= XFER_UDMA_0) { if (speed >= XFER_UDMA_0) {
multi = dma[2]; multi = dma[2];
ultra |= (scsc ? ultra6[speed - XFER_UDMA_0] : ultra |= scsc ? ultra6[speed - XFER_UDMA_0] :
ultra5[speed - XFER_UDMA_0]); ultra5[speed - XFER_UDMA_0];
mode |= (unit ? 0x30 : 0x03); mode |= unit ? 0x30 : 0x03;
} else { } else {
multi = dma[speed - XFER_MW_DMA_0]; multi = dma[speed - XFER_MW_DMA_0];
mode |= (unit ? 0x20 : 0x02); mode |= unit ? 0x20 : 0x02;
} }
if (hwif->mmio) { sil_iowrite8 (dev, mode, base + addr_mask);
hwif->OUTB(mode, base + addr_mask); sil_iowrite16(dev, multi, ma);
hwif->OUTW(multi, ma); sil_iowrite16(dev, ultra, ua);
hwif->OUTW(ultra, ua);
} else {
pci_write_config_byte(dev, addr_mask, mode);
pci_write_config_word(dev, ma, multi);
pci_write_config_word(dev, ua, ultra);
}
} }
/* returns 1 if dma irq issued, 0 otherwise */ /* returns 1 if dma irq issued, 0 otherwise */
@ -309,13 +331,14 @@ static int siimage_io_dma_test_irq(ide_drive_t *drive)
unsigned long addr = siimage_selreg(hwif, 1); unsigned long addr = siimage_selreg(hwif, 1);
/* return 1 if INTR asserted */ /* return 1 if INTR asserted */
if ((hwif->INB(hwif->dma_status) & 4) == 4) if (hwif->INB(hwif->dma_status) & 4)
return 1; return 1;
/* return 1 if Device INTR asserted */ /* return 1 if Device INTR asserted */
pci_read_config_byte(dev, addr, &dma_altstat); pci_read_config_byte(dev, addr, &dma_altstat);
if (dma_altstat & 8) if (dma_altstat & 8)
return 0; //return 1; return 0; /* return 1; */
return 0; return 0;
} }
@ -335,9 +358,9 @@ static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
= (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET]; = (void __iomem *)hwif->sata_scr[SATA_ERROR_OFFSET];
if (sata_error_addr) { if (sata_error_addr) {
unsigned long base = (unsigned long)hwif->hwif_data; unsigned long base = (unsigned long)hwif->hwif_data;
u32 ext_stat = readl((void __iomem *)(base + 0x10)); u32 ext_stat = readl((void __iomem *)(base + 0x10));
u8 watchdog = 0; u8 watchdog = 0;
if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) { if (ext_stat & ((hwif->channel) ? 0x40 : 0x10)) {
u32 sata_error = readl(sata_error_addr); u32 sata_error = readl(sata_error_addr);
@ -346,25 +369,22 @@ static int siimage_mmio_dma_test_irq(ide_drive_t *drive)
watchdog = (sata_error & 0x00680000) ? 1 : 0; watchdog = (sata_error & 0x00680000) ? 1 : 0;
printk(KERN_WARNING "%s: sata_error = 0x%08x, " printk(KERN_WARNING "%s: sata_error = 0x%08x, "
"watchdog = %d, %s\n", "watchdog = %d, %s\n",
drive->name, sata_error, watchdog, drive->name, sata_error, watchdog, __func__);
__func__); } else
} else {
watchdog = (ext_stat & 0x8000) ? 1 : 0; watchdog = (ext_stat & 0x8000) ? 1 : 0;
}
ext_stat >>= 16;
ext_stat >>= 16;
if (!(ext_stat & 0x0404) && !watchdog) if (!(ext_stat & 0x0404) && !watchdog)
return 0; return 0;
} }
/* return 1 if INTR asserted */ /* return 1 if INTR asserted */
if ((readb((void __iomem *)hwif->dma_status) & 0x04) == 0x04) if (readb((void __iomem *)hwif->dma_status) & 0x04)
return 1; return 1;
/* return 1 if Device INTR asserted */ /* return 1 if Device INTR asserted */
if ((readb((void __iomem *)addr) & 8) == 8) if (readb((void __iomem *)addr) & 8)
return 0; //return 1; return 0; /* return 1; */
return 0; return 0;
} }
@ -423,63 +443,33 @@ static void sil_sata_pre_reset(ide_drive_t *drive)
} }
/** /**
* proc_reports_siimage - add siimage controller to proc * setup_mmio_siimage - switch controller into MMIO mode
* @dev: PCI device
* @clocking: SCSC value
* @name: controller name
*
* Report the clocking mode of the controller and add it to
* the /proc interface layer
*/
static void proc_reports_siimage (struct pci_dev *dev, u8 clocking, const char *name)
{
if (!pdev_is_sata(dev)) {
printk(KERN_INFO "%s: BASE CLOCK ", name);
clocking &= 0x03;
switch (clocking) {
case 0x03: printk("DISABLED!\n"); break;
case 0x02: printk("== 2X PCI\n"); break;
case 0x01: printk("== 133\n"); break;
case 0x00: printk("== 100\n"); break;
}
}
}
/**
* setup_mmio_siimage - switch an SI controller into MMIO
* @dev: PCI device we are configuring * @dev: PCI device we are configuring
* @name: device name * @name: device name
* *
* Attempt to put the device into mmio mode. There are some slight * Attempt to put the device into MMIO mode. There are some slight
* complications here with certain systems where the mmio bar isnt * complications here with certain systems where the MMIO BAR isn't
* mapped so we have to be sure we can fall back to I/O. * mapped, so we have to be sure that we can fall back to I/O.
*/ */
static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name) static unsigned int setup_mmio_siimage(struct pci_dev *dev, const char *name)
{ {
resource_size_t bar5 = pci_resource_start(dev, 5); resource_size_t bar5 = pci_resource_start(dev, 5);
unsigned long barsize = pci_resource_len(dev, 5); unsigned long barsize = pci_resource_len(dev, 5);
u8 tmpbyte = 0;
void __iomem *ioaddr; void __iomem *ioaddr;
u32 tmp, irq_mask;
/* /*
* Drop back to PIO if we can't map the mmio. Some * Drop back to PIO if we can't map the MMIO. Some systems
* systems seem to get terminally confused in the PCI * seem to get terminally confused in the PCI spaces.
* spaces.
*/ */
if (!request_mem_region(bar5, barsize, name)) {
if(!request_mem_region(bar5, barsize, name)) printk(KERN_WARNING "siimage: IDE controller MMIO ports not "
{ "available.\n");
printk(KERN_WARNING "siimage: IDE controller MMIO ports not available.\n");
return 0; return 0;
} }
ioaddr = ioremap(bar5, barsize); ioaddr = ioremap(bar5, barsize);
if (ioaddr == NULL) {
if (ioaddr == NULL)
{
release_mem_region(bar5, barsize); release_mem_region(bar5, barsize);
return 0; return 0;
} }
@ -487,62 +477,6 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
pci_set_master(dev); pci_set_master(dev);
pci_set_drvdata(dev, (void *) ioaddr); pci_set_drvdata(dev, (void *) ioaddr);
if (pdev_is_sata(dev)) {
/* make sure IDE0/1 interrupts are not masked */
irq_mask = (1 << 22) | (1 << 23);
tmp = readl(ioaddr + 0x48);
if (tmp & irq_mask) {
tmp &= ~irq_mask;
writel(tmp, ioaddr + 0x48);
readl(ioaddr + 0x48); /* flush */
}
writel(0, ioaddr + 0x148);
writel(0, ioaddr + 0x1C8);
}
writeb(0, ioaddr + 0xB4);
writeb(0, ioaddr + 0xF4);
tmpbyte = readb(ioaddr + 0x4A);
switch(tmpbyte & 0x30) {
case 0x00:
/* In 100 MHz clocking, try and switch to 133 */
writeb(tmpbyte|0x10, ioaddr + 0x4A);
break;
case 0x10:
/* On 133Mhz clocking */
break;
case 0x20:
/* On PCIx2 clocking */
break;
case 0x30:
/* Clocking is disabled */
/* 133 clock attempt to force it on */
writeb(tmpbyte & ~0x20, ioaddr + 0x4A);
break;
}
writeb( 0x72, ioaddr + 0xA1);
writew( 0x328A, ioaddr + 0xA2);
writel(0x62DD62DD, ioaddr + 0xA4);
writel(0x43924392, ioaddr + 0xA8);
writel(0x40094009, ioaddr + 0xAC);
writeb( 0x72, ioaddr + 0xE1);
writew( 0x328A, ioaddr + 0xE2);
writel(0x62DD62DD, ioaddr + 0xE4);
writel(0x43924392, ioaddr + 0xE8);
writel(0x40094009, ioaddr + 0xEC);
if (pdev_is_sata(dev)) {
writel(0xFFFF0000, ioaddr + 0x108);
writel(0xFFFF0000, ioaddr + 0x188);
writel(0x00680000, ioaddr + 0x148);
writel(0x00680000, ioaddr + 0x1C8);
}
tmpbyte = readb(ioaddr + 0x4A);
proc_reports_siimage(dev, (tmpbyte>>4), name);
return 1; return 1;
} }
@ -552,55 +486,92 @@ static unsigned int setup_mmio_siimage (struct pci_dev *dev, const char *name)
* @name: device name * @name: device name
* *
* Perform the initial PCI set up for this device. Attempt to switch * Perform the initial PCI set up for this device. Attempt to switch
* to 133MHz clocking if the system isn't already set up to do it. * to 133 MHz clocking if the system isn't already set up to do it.
*/ */
static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const char *name) static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev,
const char *name)
{ {
u8 rev = dev->revision, tmpbyte = 0, BA5_EN = 0; unsigned long base, scsc_addr;
void __iomem *ioaddr = NULL;
u8 rev = dev->revision, tmp, BA5_EN;
pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255); pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, rev ? 1 : 255);
pci_read_config_byte(dev, 0x8A, &BA5_EN); pci_read_config_byte(dev, 0x8A, &BA5_EN);
if ((BA5_EN & 0x01) || (pci_resource_start(dev, 5))) {
if (setup_mmio_siimage(dev, name)) { if ((BA5_EN & 0x01) || pci_resource_start(dev, 5))
return 0; if (setup_mmio_siimage(dev, name))
ioaddr = pci_get_drvdata(dev);
base = (unsigned long)ioaddr;
if (ioaddr && pdev_is_sata(dev)) {
u32 tmp32, irq_mask;
/* make sure IDE0/1 interrupts are not masked */
irq_mask = (1 << 22) | (1 << 23);
tmp32 = readl(ioaddr + 0x48);
if (tmp32 & irq_mask) {
tmp32 &= ~irq_mask;
writel(tmp32, ioaddr + 0x48);
readl(ioaddr + 0x48); /* flush */
} }
writel(0, ioaddr + 0x148);
writel(0, ioaddr + 0x1C8);
} }
pci_write_config_byte(dev, 0x80, 0x00); sil_iowrite8(dev, 0, base ? (base + 0xB4) : 0x80);
pci_write_config_byte(dev, 0x84, 0x00); sil_iowrite8(dev, 0, base ? (base + 0xF4) : 0x84);
pci_read_config_byte(dev, 0x8A, &tmpbyte);
switch(tmpbyte & 0x30) { scsc_addr = base ? (base + 0x4A) : 0x8A;
case 0x00: tmp = sil_ioread8(dev, scsc_addr);
/* 133 clock attempt to force it on */
pci_write_config_byte(dev, 0x8A, tmpbyte|0x10); switch (tmp & 0x30) {
case 0x30: case 0x00:
/* if clocking is disabled */ /* On 100 MHz clocking, try and switch to 133 MHz */
/* 133 clock attempt to force it on */ sil_iowrite8(dev, tmp | 0x10, scsc_addr);
pci_write_config_byte(dev, 0x8A, tmpbyte & ~0x20); break;
case 0x10: case 0x30:
/* 133 already */ /* Clocking is disabled, attempt to force 133MHz clocking. */
break; sil_iowrite8(dev, tmp & ~0x20, scsc_addr);
case 0x20: case 0x10:
/* BIOS set PCI x2 clocking */ /* On 133Mhz clocking. */
break; break;
case 0x20:
/* On PCIx2 clocking. */
break;
} }
pci_read_config_byte(dev, 0x8A, &tmpbyte); tmp = sil_ioread8(dev, scsc_addr);
pci_write_config_byte(dev, 0xA1, 0x72); sil_iowrite8 (dev, 0x72, base + 0xA1);
pci_write_config_word(dev, 0xA2, 0x328A); sil_iowrite16(dev, 0x328A, base + 0xA2);
pci_write_config_dword(dev, 0xA4, 0x62DD62DD); sil_iowrite32(dev, 0x62DD62DD, base + 0xA4);
pci_write_config_dword(dev, 0xA8, 0x43924392); sil_iowrite32(dev, 0x43924392, base + 0xA8);
pci_write_config_dword(dev, 0xAC, 0x40094009); sil_iowrite32(dev, 0x40094009, base + 0xAC);
pci_write_config_byte(dev, 0xB1, 0x72); sil_iowrite8 (dev, 0x72, base ? (base + 0xE1) : 0xB1);
pci_write_config_word(dev, 0xB2, 0x328A); sil_iowrite16(dev, 0x328A, base ? (base + 0xE2) : 0xB2);
pci_write_config_dword(dev, 0xB4, 0x62DD62DD); sil_iowrite32(dev, 0x62DD62DD, base ? (base + 0xE4) : 0xB4);
pci_write_config_dword(dev, 0xB8, 0x43924392); sil_iowrite32(dev, 0x43924392, base ? (base + 0xE8) : 0xB8);
pci_write_config_dword(dev, 0xBC, 0x40094009); sil_iowrite32(dev, 0x40094009, base ? (base + 0xEC) : 0xBC);
if (base && pdev_is_sata(dev)) {
writel(0xFFFF0000, ioaddr + 0x108);
writel(0xFFFF0000, ioaddr + 0x188);
writel(0x00680000, ioaddr + 0x148);
writel(0x00680000, ioaddr + 0x1C8);
}
/* report the clocking mode of the controller */
if (!pdev_is_sata(dev)) {
static const char *clk_str[] =
{ "== 100", "== 133", "== 2X PCI", "DISABLED!" };
tmp >>= 4;
printk(KERN_INFO "%s: BASE CLOCK %s\n", name, clk_str[tmp & 3]);
}
proc_reports_siimage(dev, (tmpbyte>>4), name);
return 0; return 0;
} }
@ -610,8 +581,7 @@ static unsigned int __devinit init_chipset_siimage(struct pci_dev *dev, const ch
* *
* The basic setup here is fairly simple, we can use standard MMIO * The basic setup here is fairly simple, we can use standard MMIO
* operations. However we do have to set the taskfile register offsets * operations. However we do have to set the taskfile register offsets
* by hand as there isnt a standard defined layout for them this * by hand as there isn't a standard defined layout for them this time.
* time.
* *
* The hardware supports buffered taskfiles and also some rather nice * The hardware supports buffered taskfiles and also some rather nice
* extended PRD tables. For better SI3112 support use the libata driver * extended PRD tables. For better SI3112 support use the libata driver
@ -622,23 +592,20 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
struct pci_dev *dev = to_pci_dev(hwif->dev); struct pci_dev *dev = to_pci_dev(hwif->dev);
void *addr = pci_get_drvdata(dev); void *addr = pci_get_drvdata(dev);
u8 ch = hwif->channel; u8 ch = hwif->channel;
unsigned long base;
struct ide_io_ports *io_ports = &hwif->io_ports; struct ide_io_ports *io_ports = &hwif->io_ports;
unsigned long base;
/* /*
* Fill in the basic HWIF bits * Fill in the basic hwif bits
*/ */
hwif->host_flags |= IDE_HFLAG_MMIO;
default_hwif_mmiops(hwif); default_hwif_mmiops(hwif);
hwif->hwif_data = addr; hwif->hwif_data = addr;
/* /*
* Now set up the hw. We have to do this ourselves as * Now set up the hw. We have to do this ourselves as the
* the MMIO layout isnt the same as the standard port * MMIO layout isn't the same as the standard port based I/O.
* based I/O
*/ */
memset(io_ports, 0, sizeof(*io_ports)); memset(io_ports, 0, sizeof(*io_ports));
base = (unsigned long)addr; base = (unsigned long)addr;
@ -648,9 +615,8 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
base += 0x80; base += 0x80;
/* /*
* The buffered task file doesn't have status/control * The buffered task file doesn't have status/control, so we
* so we can't currently use it sanely since we want to * can't currently use it sanely since we want to use LBA48 mode.
* use LBA48 mode.
*/ */
io_ports->data_addr = base; io_ports->data_addr = base;
io_ports->error_addr = base + 1; io_ports->error_addr = base + 1;
@ -680,19 +646,17 @@ static void __devinit init_mmio_iops_siimage(ide_hwif_t *hwif)
static int is_dev_seagate_sata(ide_drive_t *drive) static int is_dev_seagate_sata(ide_drive_t *drive)
{ {
const char *s = &drive->id->model[0]; const char *s = &drive->id->model[0];
unsigned len; unsigned len = strnlen(s, sizeof(drive->id->model));
len = strnlen(s, sizeof(drive->id->model)); if ((len > 4) && (!memcmp(s, "ST", 2)))
if ((len > 4) && (!memcmp(s, "ST", 2))) {
if ((!memcmp(s + len - 2, "AS", 2)) || if ((!memcmp(s + len - 2, "AS", 2)) ||
(!memcmp(s + len - 3, "ASL", 3))) { (!memcmp(s + len - 3, "ASL", 3))) {
printk(KERN_INFO "%s: applying pessimistic Seagate " printk(KERN_INFO "%s: applying pessimistic Seagate "
"errata fix\n", drive->name); "errata fix\n", drive->name);
return 1; return 1;
} }
}
return 0; return 0;
} }
@ -709,7 +673,7 @@ static void __devinit sil_quirkproc(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = drive->hwif; ide_hwif_t *hwif = drive->hwif;
/* Try and raise the rqsize */ /* Try and rise the rqsize */
if (!is_sata(hwif) || !is_dev_seagate_sata(drive)) if (!is_sata(hwif) || !is_dev_seagate_sata(drive))
hwif->rqsize = 128; hwif->rqsize = 128;
} }
@ -743,20 +707,14 @@ static void __devinit init_iops_siimage(ide_hwif_t *hwif)
* sil_cable_detect - cable detection * sil_cable_detect - cable detection
* @hwif: interface to check * @hwif: interface to check
* *
* Check for the presence of an ATA66 capable cable on the * Check for the presence of an ATA66 capable cable on the interface.
* interface.
*/ */
static u8 __devinit sil_cable_detect(ide_hwif_t *hwif) static u8 __devinit sil_cable_detect(ide_hwif_t *hwif)
{ {
struct pci_dev *dev = to_pci_dev(hwif->dev); struct pci_dev *dev = to_pci_dev(hwif->dev);
unsigned long addr = siimage_selreg(hwif, 0); unsigned long addr = siimage_selreg(hwif, 0);
u8 ata66 = 0; u8 ata66 = sil_ioread8(dev, addr);
if (pci_get_drvdata(dev) == NULL)
pci_read_config_byte(dev, addr, &ata66);
else
ata66 = hwif->INB(addr);
return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40; return (ata66 & 0x01) ? ATA_CBL_PATA80 : ATA_CBL_PATA40;
} }
@ -802,15 +760,16 @@ static const struct ide_port_info siimage_chipsets[] __devinitdata = {
}; };
/** /**
* siimage_init_one - pci layer discovery entry * siimage_init_one - PCI layer discovery entry
* @dev: PCI device * @dev: PCI device
* @id: ident table entry * @id: ident table entry
* *
* Called by the PCI code when it finds an SI680 or SI3112 controller. * Called by the PCI code when it finds an SiI680 or SiI3112 controller.
* We then use the IDE PCI generic helper to do most of the work. * We then use the IDE PCI generic helper to do most of the work.
*/ */
static int __devinit siimage_init_one(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit siimage_init_one(struct pci_dev *dev,
const struct pci_device_id *id)
{ {
struct ide_port_info d; struct ide_port_info d;
u8 idx = id->driver_data; u8 idx = id->driver_data;

View file

@ -941,6 +941,7 @@ static const struct ide_port_info pmac_port_info = {
.port_ops = &pmac_ide_port_ops, .port_ops = &pmac_ide_port_ops,
.host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA | .host_flags = IDE_HFLAG_SET_PIO_MODE_KEEP_DMA |
IDE_HFLAG_POST_SET_MODE | IDE_HFLAG_POST_SET_MODE |
IDE_HFLAG_MMIO |
IDE_HFLAG_UNMASK_IRQS, IDE_HFLAG_UNMASK_IRQS,
.pio_mask = ATA_PIO4, .pio_mask = ATA_PIO4,
.mwdma_mask = ATA_MWDMA2, .mwdma_mask = ATA_MWDMA2,

View file

@ -38,7 +38,6 @@ config PCMCIA_DEBUG
config PCMCIA config PCMCIA
tristate "16-bit PCMCIA support" tristate "16-bit PCMCIA support"
select CRC32 select CRC32
select HAVE_IDE
default y default y
---help--- ---help---
This option enables support for 16-bit PCMCIA cards. Most older This option enables support for 16-bit PCMCIA cards. Most older

View file

@ -134,6 +134,7 @@ static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount) unsigned int bcount)
{ {
ide_hwif_t *hwif = drive->hwif;
int count; int count;
char *buf; char *buf;
@ -145,14 +146,12 @@ static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
local_irq_save(flags); local_irq_save(flags);
buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) + buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) +
pc->sg->offset; pc->sg->offset;
drive->hwif->atapi_input_bytes(drive, hwif->input_data(drive, NULL, buf + pc->b_count, count);
buf + pc->b_count, count);
kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
local_irq_restore(flags); local_irq_restore(flags);
} else { } else {
buf = sg_virt(pc->sg); buf = sg_virt(pc->sg);
drive->hwif->atapi_input_bytes(drive, hwif->input_data(drive, NULL, buf + pc->b_count, count);
buf + pc->b_count, count);
} }
bcount -= count; pc->b_count += count; bcount -= count; pc->b_count += count;
if (pc->b_count == pc->sg->length) { if (pc->b_count == pc->sg->length) {
@ -165,13 +164,14 @@ static void idescsi_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
if (bcount) { if (bcount) {
printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n");
ide_atapi_discard_data(drive, bcount); ide_pad_transfer(drive, 0, bcount);
} }
} }
static void idescsi_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, static void idescsi_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
unsigned int bcount) unsigned int bcount)
{ {
ide_hwif_t *hwif = drive->hwif;
int count; int count;
char *buf; char *buf;
@ -183,14 +183,12 @@ static void idescsi_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
local_irq_save(flags); local_irq_save(flags);
buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) + buf = kmap_atomic(sg_page(pc->sg), KM_IRQ0) +
pc->sg->offset; pc->sg->offset;
drive->hwif->atapi_output_bytes(drive, hwif->output_data(drive, NULL, buf + pc->b_count, count);
buf + pc->b_count, count);
kunmap_atomic(buf - pc->sg->offset, KM_IRQ0); kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
local_irq_restore(flags); local_irq_restore(flags);
} else { } else {
buf = sg_virt(pc->sg); buf = sg_virt(pc->sg);
drive->hwif->atapi_output_bytes(drive, hwif->output_data(drive, NULL, buf + pc->b_count, count);
buf + pc->b_count, count);
} }
bcount -= count; pc->b_count += count; bcount -= count; pc->b_count += count;
if (pc->b_count == pc->sg->length) { if (pc->b_count == pc->sg->length) {
@ -203,7 +201,7 @@ static void idescsi_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc,
if (bcount) { if (bcount) {
printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n");
ide_atapi_write_zeros(drive, bcount); ide_pad_transfer(drive, 1, bcount);
} }
} }
@ -258,7 +256,8 @@ idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT)) if (ide_read_status(drive) & (BUSY_STAT | DRQ_STAT))
/* force an abort */ /* force an abort */
hwif->OUTB(WIN_IDLEIMMEDIATE, hwif->io_ports.command_addr); hwif->OUTBSYNC(drive, WIN_IDLEIMMEDIATE,
hwif->io_ports.command_addr);
rq->errors++; rq->errors++;
@ -431,14 +430,15 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
idescsi_input_buffers(drive, pc, idescsi_input_buffers(drive, pc,
temp); temp);
else else
drive->hwif->atapi_input_bytes(drive, pc->cur_pos, temp); hwif->input_data(drive, NULL,
pc->cur_pos, temp);
printk(KERN_ERR "ide-scsi: transferred" printk(KERN_ERR "ide-scsi: transferred"
" %d of %d bytes\n", " %d of %d bytes\n",
temp, bcount); temp, bcount);
} }
pc->xferred += temp; pc->xferred += temp;
pc->cur_pos += temp; pc->cur_pos += temp;
ide_atapi_discard_data(drive, bcount - temp); ide_pad_transfer(drive, 0, bcount - temp);
ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry); ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
return ide_started; return ide_started;
} }
@ -452,15 +452,13 @@ static ide_startstop_t idescsi_pc_intr (ide_drive_t *drive)
if (pc->sg) if (pc->sg)
idescsi_input_buffers(drive, pc, bcount); idescsi_input_buffers(drive, pc, bcount);
else else
hwif->atapi_input_bytes(drive, pc->cur_pos, hwif->input_data(drive, NULL, pc->cur_pos, bcount);
bcount);
} else { } else {
pc->flags |= PC_FLAG_WRITING; pc->flags |= PC_FLAG_WRITING;
if (pc->sg) if (pc->sg)
idescsi_output_buffers(drive, pc, bcount); idescsi_output_buffers(drive, pc, bcount);
else else
hwif->atapi_output_bytes(drive, pc->cur_pos, hwif->output_data(drive, NULL, pc->cur_pos, bcount);
bcount);
} }
/* Update the current position */ /* Update the current position */
pc->xferred += bcount; pc->xferred += bcount;
@ -493,8 +491,10 @@ static ide_startstop_t idescsi_transfer_pc(ide_drive_t *drive)
BUG_ON(HWGROUP(drive)->handler != NULL); BUG_ON(HWGROUP(drive)->handler != NULL);
/* Set the interrupt routine */ /* Set the interrupt routine */
ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry); ide_set_handler(drive, &idescsi_pc_intr, get_timeout(pc), idescsi_expiry);
/* Send the actual packet */ /* Send the actual packet */
drive->hwif->atapi_output_bytes(drive, scsi->pc->c, 12); hwif->output_data(drive, NULL, scsi->pc->c, 12);
if (pc->flags & PC_FLAG_DMA_OK) { if (pc->flags & PC_FLAG_DMA_OK) {
pc->flags |= PC_FLAG_DMA_IN_PROGRESS; pc->flags |= PC_FLAG_DMA_IN_PROGRESS;
hwif->dma_ops->dma_start(drive); hwif->dma_ops->dma_start(drive);
@ -574,7 +574,7 @@ static ide_startstop_t idescsi_issue_pc(ide_drive_t *drive,
return ide_started; return ide_started;
} else { } else {
/* Issue the packet command */ /* Issue the packet command */
hwif->OUTB(WIN_PACKETCMD, hwif->io_ports.command_addr); ide_execute_pkt_cmd(drive);
return idescsi_transfer_pc(drive); return idescsi_transfer_pc(drive);
} }
} }

View file

@ -427,6 +427,8 @@ struct ide_dma_ops {
void (*dma_timeout)(struct ide_drive_s *); void (*dma_timeout)(struct ide_drive_s *);
}; };
struct ide_task_s;
typedef struct hwif_s { typedef struct hwif_s {
struct hwif_s *next; /* for linked-list in ide_hwgroup_t */ struct hwif_s *next; /* for linked-list in ide_hwgroup_t */
struct hwif_s *mate; /* other hwif from same PCI chip */ struct hwif_s *mate; /* other hwif from same PCI chip */
@ -467,24 +469,18 @@ typedef struct hwif_s {
const struct ide_port_ops *port_ops; const struct ide_port_ops *port_ops;
const struct ide_dma_ops *dma_ops; const struct ide_dma_ops *dma_ops;
void (*ata_input_data)(ide_drive_t *, void *, u32); void (*tf_load)(ide_drive_t *, struct ide_task_s *);
void (*ata_output_data)(ide_drive_t *, void *, u32); void (*tf_read)(ide_drive_t *, struct ide_task_s *);
void (*atapi_input_bytes)(ide_drive_t *, void *, u32); void (*input_data)(ide_drive_t *, struct request *, void *, unsigned);
void (*atapi_output_bytes)(ide_drive_t *, void *, u32); void (*output_data)(ide_drive_t *, struct request *, void *, unsigned);
void (*ide_dma_clear_irq)(ide_drive_t *drive); void (*ide_dma_clear_irq)(ide_drive_t *drive);
void (*OUTB)(u8 addr, unsigned long port); void (*OUTB)(u8 addr, unsigned long port);
void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port); void (*OUTBSYNC)(ide_drive_t *drive, u8 addr, unsigned long port);
void (*OUTW)(u16 addr, unsigned long port);
void (*OUTSW)(unsigned long port, void *addr, u32 count);
void (*OUTSL)(unsigned long port, void *addr, u32 count);
u8 (*INB)(unsigned long port); u8 (*INB)(unsigned long port);
u16 (*INW)(unsigned long port);
void (*INSW)(unsigned long port, void *addr, u32 count);
void (*INSL)(unsigned long port, void *addr, u32 count);
/* dma physical region descriptor table (cpu view) */ /* dma physical region descriptor table (cpu view) */
unsigned int *dmatable_cpu; unsigned int *dmatable_cpu;
@ -509,10 +505,7 @@ typedef struct hwif_s {
unsigned long dma_base; /* base addr for dma ports */ unsigned long dma_base; /* base addr for dma ports */
unsigned long dma_command; /* dma command register */ unsigned long dma_command; /* dma command register */
unsigned long dma_vendor1; /* dma vendor 1 register */
unsigned long dma_status; /* dma status register */ unsigned long dma_status; /* dma status register */
unsigned long dma_vendor3; /* dma vendor 3 register */
unsigned long dma_prdtable; /* actual prd table address */
unsigned long config_data; /* for use by chipset-specific code */ unsigned long config_data; /* for use by chipset-specific code */
unsigned long select_data; /* for use by chipset-specific code */ unsigned long select_data; /* for use by chipset-specific code */
@ -547,7 +540,7 @@ typedef ide_startstop_t (ide_handler_t)(ide_drive_t *);
typedef int (ide_expiry_t)(ide_drive_t *); typedef int (ide_expiry_t)(ide_drive_t *);
/* used by ide-cd, ide-floppy, etc. */ /* used by ide-cd, ide-floppy, etc. */
typedef void (xfer_func_t)(ide_drive_t *, void *, u32); typedef void (xfer_func_t)(ide_drive_t *, struct request *rq, void *, unsigned);
typedef struct hwgroup_s { typedef struct hwgroup_s {
/* irq handler, if active */ /* irq handler, if active */
@ -829,6 +822,10 @@ extern void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, unsigne
void ide_execute_command(ide_drive_t *, u8, ide_handler_t *, unsigned int, void ide_execute_command(ide_drive_t *, u8, ide_handler_t *, unsigned int,
ide_expiry_t *); ide_expiry_t *);
void ide_execute_pkt_cmd(ide_drive_t *);
void ide_pad_transfer(ide_drive_t *, int, int);
ide_startstop_t __ide_error(ide_drive_t *, struct request *, u8, u8); ide_startstop_t __ide_error(ide_drive_t *, struct request *, u8, u8);
ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat); ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat);
@ -965,8 +962,7 @@ typedef struct ide_task_s {
void *special; /* valid_t generally */ void *special; /* valid_t generally */
} ide_task_t; } ide_task_t;
void ide_tf_load(ide_drive_t *, ide_task_t *); void ide_tf_dump(const char *, struct ide_taskfile *);
void ide_tf_read(ide_drive_t *, ide_task_t *);
extern void SELECT_DRIVE(ide_drive_t *); extern void SELECT_DRIVE(ide_drive_t *);
extern void SELECT_MASK(ide_drive_t *, int); extern void SELECT_MASK(ide_drive_t *, int);
@ -1072,6 +1068,8 @@ enum {
IDE_HFLAG_NO_DMA = (1 << 14), IDE_HFLAG_NO_DMA = (1 << 14),
/* check if host is PCI IDE device before allowing DMA */ /* check if host is PCI IDE device before allowing DMA */
IDE_HFLAG_NO_AUTODMA = (1 << 15), IDE_HFLAG_NO_AUTODMA = (1 << 15),
/* host uses MMIO */
IDE_HFLAG_MMIO = (1 << 16),
/* host is CS5510/CS5520 */ /* host is CS5510/CS5520 */
IDE_HFLAG_CS5520 = IDE_HFLAG_VDMA, IDE_HFLAG_CS5520 = IDE_HFLAG_VDMA,
/* no LBA48 */ /* no LBA48 */
@ -1360,27 +1358,4 @@ static inline u8 ide_read_error(ide_drive_t *drive)
return hwif->INB(hwif->io_ports.error_addr); return hwif->INB(hwif->io_ports.error_addr);
} }
/*
* Too bad. The drive wants to send us data which we are not ready to accept.
* Just throw it away.
*/
static inline void ide_atapi_discard_data(ide_drive_t *drive, unsigned bcount)
{
ide_hwif_t *hwif = drive->hwif;
/* FIXME: use ->atapi_input_bytes */
while (bcount--)
(void)hwif->INB(hwif->io_ports.data_addr);
}
static inline void ide_atapi_write_zeros(ide_drive_t *drive, unsigned bcount)
{
ide_hwif_t *hwif = drive->hwif;
/* FIXME: use ->atapi_output_bytes */
while (bcount--)
hwif->OUTB(0, hwif->io_ports.data_addr);
}
#endif /* _IDE_H */ #endif /* _IDE_H */