?? ide-iops.c
字號:
/* * linux/drivers/ide/ide-iops.c Version 0.37 Mar 05, 2003 * * Copyright (C) 2000-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2003 Red Hat <alan@redhat.com> * * */#include <linux/config.h>#define __NO_VERSION__#include <linux/module.h>#include <linux/types.h>#include <linux/string.h>#include <linux/kernel.h>#include <linux/timer.h>#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/major.h>#include <linux/errno.h>#include <linux/genhd.h>#include <linux/blkpg.h>#include <linux/slab.h>#include <linux/pci.h>#include <linux/delay.h>#include <linux/hdreg.h>#include <linux/ide.h>#include <asm/byteorder.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/bitops.h>/* * IDE operator we assign to an unplugged device so that * we don't trash new hardware assigned the same resources */ static u8 ide_unplugged_inb (unsigned long port){ return 0xFF;}static u16 ide_unplugged_inw (unsigned long port){ return 0xFFFF;}static void ide_unplugged_insw (unsigned long port, void *addr, u32 count){}static u32 ide_unplugged_inl (unsigned long port){ return 0xFFFFFFFF;}static void ide_unplugged_insl (unsigned long port, void *addr, u32 count){}static void ide_unplugged_outb (u8 addr, unsigned long port){}static void ide_unplugged_outbsync (ide_drive_t *drive, u8 addr, unsigned long port){}static void ide_unplugged_outw (u16 addr, unsigned long port){}static void ide_unplugged_outsw (unsigned long port, void *addr, u32 count){}static void ide_unplugged_outl (u32 addr, unsigned long port){}static void ide_unplugged_outsl (unsigned long port, void *addr, u32 count){}void unplugged_hwif_iops (ide_hwif_t *hwif){ hwif->OUTB = ide_unplugged_outb; hwif->OUTBSYNC = ide_unplugged_outbsync; hwif->OUTW = ide_unplugged_outw; hwif->OUTL = ide_unplugged_outl; hwif->OUTSW = ide_unplugged_outsw; hwif->OUTSL = ide_unplugged_outsl; hwif->INB = ide_unplugged_inb; hwif->INW = ide_unplugged_inw; hwif->INL = ide_unplugged_inl; hwif->INSW = ide_unplugged_insw; hwif->INSL = ide_unplugged_insl;}EXPORT_SYMBOL(unplugged_hwif_iops);/* * Conventional PIO operations for ATA devices */static u8 ide_inb (unsigned long port){#if defined( CONFIG_ARCH_EDB7312 ) return IN_BYTE(port);#elif defined( CONFIG_ARCH_EP93XX ) return (u8) ep93xx_pcmcia_ide_inb(port);#else return (u8) inb(port);#endif}static u16 ide_inw (unsigned long port){#ifdef CONFIG_ARCH_EP93XX return (u16) ep93xx_pcmcia_ide_inw(port);#else return (u16) inw(port);#endif}static void ide_insw (unsigned long port, void *addr, u32 count){#ifdef CONFIG_ARCH_EP93XX return ep93xx_pcmcia_ide_insw(port, addr, count);#else return insw(port, addr, count);#endif}static u32 ide_inl (unsigned long port){ return (u32) inl(port);}static void ide_insl (unsigned long port, void *addr, u32 count){ insl(port, addr, count);}static void ide_outb (u8 addr, unsigned long port){#if defined( CONFIG_ARCH_EDB7312 ) OUT_BYTE(addr, port);#elif defined( CONFIG_ARCH_EP93XX ) ep93xx_pcmcia_ide_outb(addr, port);#else outb(addr, port);#endif}static void ide_outbsync (ide_drive_t *drive, u8 addr, unsigned long port){#ifdef CONFIG_ARCH_EP93XX ep93xx_pcmcia_ide_outb(addr, port);#else outb(addr, port);#endif}static void ide_outw (u16 addr, unsigned long port){#ifdef CONFIG_ARCH_EP93XX ep93xx_pcmcia_ide_outw(addr, port);#else outw(addr, port);#endif}static void ide_outsw (unsigned long port, void *addr, u32 count){#ifdef CONFIG_ARCH_EP93XX ep93xx_pcmcia_ide_outsw(port, addr, count);#else outsw(port, addr, count);#endif}static void ide_outl (u32 addr, unsigned long port){ outl(addr, port);}static void ide_outsl (unsigned long port, void *addr, u32 count){ outsl(port, addr, count);}void default_hwif_iops (ide_hwif_t *hwif){ hwif->OUTB = ide_outb; hwif->OUTBSYNC = ide_outbsync; hwif->OUTW = ide_outw; hwif->OUTL = ide_outl; hwif->OUTSW = ide_outsw; hwif->OUTSL = ide_outsl; hwif->INB = ide_inb; hwif->INW = ide_inw; hwif->INL = ide_inl; hwif->INSW = ide_insw; hwif->INSL = ide_insl;}EXPORT_SYMBOL(default_hwif_iops);/* * MMIO operations, typically used for SATA controllers */static u8 ide_mm_inb (unsigned long port){ return (u8) readb(port);}static u16 ide_mm_inw (unsigned long port){ return (u16) readw(port);}static void ide_mm_insw (unsigned long port, void *addr, u32 count){ __ide_mm_insw(port, addr, count);}static u32 ide_mm_inl (unsigned long port){ return (u32) readl(port);}static void ide_mm_insl (unsigned long port, void *addr, u32 count){ __ide_mm_insl(port, addr, count);}static void ide_mm_outb (u8 value, unsigned long port){ writeb(value, port);}static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long port){ writeb(value, port); }static void ide_mm_outw (u16 value, unsigned long port){ writew(value, port);}static void ide_mm_outsw (unsigned long port, void *addr, u32 count){ __ide_mm_outsw(port, addr, count);}static void ide_mm_outl (u32 value, unsigned long port){ writel(value, port);}static void ide_mm_outsl (unsigned long port, void *addr, u32 count){ __ide_mm_outsl(port, addr, count);}void default_hwif_mmiops (ide_hwif_t *hwif){ hwif->OUTB = ide_mm_outb; /* Most systems will need to override OUTBSYNC, alas however this one is controller specific! */ hwif->OUTBSYNC = ide_mm_outbsync; hwif->OUTW = ide_mm_outw; hwif->OUTL = ide_mm_outl; hwif->OUTSW = ide_mm_outsw; hwif->OUTSL = ide_mm_outsl; hwif->INB = ide_mm_inb; hwif->INW = ide_mm_inw; hwif->INL = ide_mm_inl; hwif->INSW = ide_mm_insw; hwif->INSL = ide_mm_insl;}EXPORT_SYMBOL(default_hwif_mmiops);void default_hwif_transport (ide_hwif_t *hwif){ hwif->ata_input_data = ata_input_data; hwif->ata_output_data = ata_output_data; hwif->atapi_input_bytes = atapi_input_bytes; hwif->atapi_output_bytes = atapi_output_bytes;}EXPORT_SYMBOL(default_hwif_transport);u32 read_24 (ide_drive_t *drive){ u8 hcyl = HWIF(drive)->INB(IDE_HCYL_REG); u8 lcyl = HWIF(drive)->INB(IDE_LCYL_REG); u8 sect = HWIF(drive)->INB(IDE_SECTOR_REG); return (hcyl<<16)|(lcyl<<8)|sect;}EXPORT_SYMBOL(read_24);void SELECT_DRIVE (ide_drive_t *drive){ if (HWIF(drive)->selectproc) HWIF(drive)->selectproc(drive); HWIF(drive)->OUTB(drive->select.all, IDE_SELECT_REG);}EXPORT_SYMBOL(SELECT_DRIVE);void SELECT_INTERRUPT (ide_drive_t *drive){ if (HWIF(drive)->intrproc) HWIF(drive)->intrproc(drive); else HWIF(drive)->OUTB(drive->ctl|2, IDE_CONTROL_REG);}EXPORT_SYMBOL(SELECT_INTERRUPT);void SELECT_MASK (ide_drive_t *drive, int mask){ if (HWIF(drive)->maskproc) HWIF(drive)->maskproc(drive, mask);}EXPORT_SYMBOL(SELECT_MASK);void QUIRK_LIST (ide_drive_t *drive){ if (HWIF(drive)->quirkproc) drive->quirk_list = HWIF(drive)->quirkproc(drive);}EXPORT_SYMBOL(QUIRK_LIST);/* * Some localbus EIDE interfaces require a special access sequence * when using 32-bit I/O instructions to transfer data. We call this * the "vlb_sync" sequence, which consists of three successive reads * of the sector count register location, with interrupts disabled * to ensure that the reads all happen together. */void ata_vlb_sync (ide_drive_t *drive, ide_ioreg_t port){ (void) HWIF(drive)->INB(port); (void) HWIF(drive)->INB(port); (void) HWIF(drive)->INB(port);}EXPORT_SYMBOL(ata_vlb_sync);/* * This is used for most PIO data transfers *from* the IDE interface */void ata_input_data (ide_drive_t *drive, void *buffer, u32 wcount){ ide_hwif_t *hwif = HWIF(drive); u8 io_32bit = drive->io_32bit; if (io_32bit) { if (io_32bit & 2) { unsigned long flags; local_irq_save(flags); ata_vlb_sync(drive, IDE_NSECTOR_REG); hwif->INSL(IDE_DATA_REG, buffer, wcount); local_irq_restore(flags); } else hwif->INSL(IDE_DATA_REG, buffer, wcount); } else { hwif->INSW(IDE_DATA_REG, buffer, wcount<<1); }}EXPORT_SYMBOL(ata_input_data);/* * This is used for most PIO data transfers *to* the IDE interface */void ata_output_data (ide_drive_t *drive, void *buffer, u32 wcount){ ide_hwif_t *hwif = HWIF(drive); u8 io_32bit = drive->io_32bit; if (io_32bit) { if (io_32bit & 2) { unsigned long flags; local_irq_save(flags); ata_vlb_sync(drive, IDE_NSECTOR_REG); hwif->OUTSL(IDE_DATA_REG, buffer, wcount); local_irq_restore(flags); } else hwif->OUTSL(IDE_DATA_REG, buffer, wcount); } else { hwif->OUTSW(IDE_DATA_REG, buffer, wcount<<1); }}EXPORT_SYMBOL(ata_output_data);/* * The following routines are mainly used by the ATAPI drivers. * * These routines will round up any request for an odd number of bytes, * so if an odd bytecount is specified, be sure that there's at least one * extra byte allocated for the buffer. */void atapi_input_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 */ insw_swapw(IDE_DATA_REG, buffer, bytecount / 2); return; }#endif /* CONFIG_ATARI || CONFIG_Q40 */ hwif->ata_input_data(drive, buffer, bytecount / 4); if ((bytecount & 0x03) >= 2) hwif->INSW(IDE_DATA_REG, ((u8 *)buffer)+(bytecount & ~0x03), 1);}EXPORT_SYMBOL(atapi_input_bytes);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(IDE_DATA_REG, buffer, bytecount / 2); return; }#endif /* CONFIG_ATARI || CONFIG_Q40 */ hwif->ata_output_data(drive, buffer, bytecount / 4); if ((bytecount & 0x03) >= 2) hwif->OUTSW(IDE_DATA_REG, ((u8*)buffer)+(bytecount & ~0x03), 1);}EXPORT_SYMBOL(atapi_output_bytes);/* * Beginning of Taskfile OPCODE Library and feature sets. */void ide_fix_driveid (struct hd_driveid *id)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -