ide-iops.c

来自「ep9315平台下硬盘驱动的源码」· C语言 代码 · 共 1,372 行 · 第 1/3 页

C
1,372
字号
/* * 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 + =
减小字号Ctrl + -
显示快捷键?