⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ide-iops.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * 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/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 <linux/bitops.h>#include <linux/nmi.h>#include <asm/byteorder.h>#include <asm/irq.h>#include <asm/uaccess.h>#include <asm/io.h>/* *	Conventional PIO operations for ATA devices */static u8 ide_inb (unsigned long 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){	outb(val, port);}static void ide_outbsync (ide_drive_t *drive, u8 addr, unsigned long 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){	hwif->OUTB	= ide_outb;	hwif->OUTBSYNC	= ide_outbsync;	hwif->OUTW	= ide_outw;	hwif->OUTSW	= ide_outsw;	hwif->OUTSL	= ide_outsl;	hwif->INB	= ide_inb;	hwif->INW	= ide_inw;	hwif->INSW	= ide_insw;	hwif->INSL	= ide_insl;}/* *	MMIO operations, typically used for SATA controllers */static u8 ide_mm_inb (unsigned long 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){	writeb(value, (void __iomem *) port);}static void ide_mm_outbsync (ide_drive_t *drive, u8 value, unsigned long 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){	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->OUTSW	= ide_mm_outsw;	hwif->OUTSL	= ide_mm_outsl;	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);u32 ide_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;}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);}void SELECT_MASK (ide_drive_t *drive, int mask){	if (HWIF(drive)->maskproc)		HWIF(drive)->maskproc(drive, mask);}void QUIRK_LIST (ide_drive_t *drive){	if (HWIF(drive)->quirkproc)		drive->quirk_list = HWIF(drive)->quirkproc(drive);}/* * 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. */static void ata_vlb_sync(ide_drive_t *drive, unsigned long port){	(void) HWIF(drive)->INB(port);	(void) HWIF(drive)->INB(port);	(void) HWIF(drive)->INB(port);}/* * This is used for most PIO data transfers *from* the IDE interface */static 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);	}}/* * 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){	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);	}}/* * 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. */static 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);}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(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);}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;}void ide_fix_driveid (struct hd_driveid *id){#ifndef __LITTLE_ENDIAN# ifdef __BIG_ENDIAN	int i;	u16 *stringcast;	id->config         = __le16_to_cpu(id->config);	id->cyls           = __le16_to_cpu(id->cyls);	id->reserved2      = __le16_to_cpu(id->reserved2);	id->heads          = __le16_to_cpu(id->heads);	id->track_bytes    = __le16_to_cpu(id->track_bytes);	id->sector_bytes   = __le16_to_cpu(id->sector_bytes);	id->sectors        = __le16_to_cpu(id->sectors);	id->vendor0        = __le16_to_cpu(id->vendor0);	id->vendor1        = __le16_to_cpu(id->vendor1);	id->vendor2        = __le16_to_cpu(id->vendor2);	stringcast = (u16 *)&id->serial_no[0];	for (i = 0; i < (20/2); i++)		stringcast[i] = __le16_to_cpu(stringcast[i]);	id->buf_type       = __le16_to_cpu(id->buf_type);	id->buf_size       = __le16_to_cpu(id->buf_size);	id->ecc_bytes      = __le16_to_cpu(id->ecc_bytes);	stringcast = (u16 *)&id->fw_rev[0];	for (i = 0; i < (8/2); i++)		stringcast[i] = __le16_to_cpu(stringcast[i]);	stringcast = (u16 *)&id->model[0];	for (i = 0; i < (40/2); i++)		stringcast[i] = __le16_to_cpu(stringcast[i]);	id->dword_io       = __le16_to_cpu(id->dword_io);	id->reserved50     = __le16_to_cpu(id->reserved50);	id->field_valid    = __le16_to_cpu(id->field_valid);	id->cur_cyls       = __le16_to_cpu(id->cur_cyls);	id->cur_heads      = __le16_to_cpu(id->cur_heads);	id->cur_sectors    = __le16_to_cpu(id->cur_sectors);	id->cur_capacity0  = __le16_to_cpu(id->cur_capacity0);	id->cur_capacity1  = __le16_to_cpu(id->cur_capacity1);	id->lba_capacity   = __le32_to_cpu(id->lba_capacity);	id->dma_1word      = __le16_to_cpu(id->dma_1word);	id->dma_mword      = __le16_to_cpu(id->dma_mword);	id->eide_pio_modes = __le16_to_cpu(id->eide_pio_modes);	id->eide_dma_min   = __le16_to_cpu(id->eide_dma_min);	id->eide_dma_time  = __le16_to_cpu(id->eide_dma_time);	id->eide_pio       = __le16_to_cpu(id->eide_pio);	id->eide_pio_iordy = __le16_to_cpu(id->eide_pio_iordy);	for (i = 0; i < 2; ++i)		id->words69_70[i] = __le16_to_cpu(id->words69_70[i]);	for (i = 0; i < 4; ++i)		id->words71_74[i] = __le16_to_cpu(id->words71_74[i]);	id->queue_depth    = __le16_to_cpu(id->queue_depth);	for (i = 0; i < 4; ++i)		id->words76_79[i] = __le16_to_cpu(id->words76_79[i]);	id->major_rev_num  = __le16_to_cpu(id->major_rev_num);	id->minor_rev_num  = __le16_to_cpu(id->minor_rev_num);	id->command_set_1  = __le16_to_cpu(id->command_set_1);	id->command_set_2  = __le16_to_cpu(id->command_set_2);	id->cfsse          = __le16_to_cpu(id->cfsse);	id->cfs_enable_1   = __le16_to_cpu(id->cfs_enable_1);	id->cfs_enable_2   = __le16_to_cpu(id->cfs_enable_2);	id->csf_default    = __le16_to_cpu(id->csf_default);	id->dma_ultra      = __le16_to_cpu(id->dma_ultra);	id->trseuc         = __le16_to_cpu(id->trseuc);	id->trsEuc         = __le16_to_cpu(id->trsEuc);	id->CurAPMvalues   = __le16_to_cpu(id->CurAPMvalues);	id->mprc           = __le16_to_cpu(id->mprc);	id->hw_config      = __le16_to_cpu(id->hw_config);	id->acoustic       = __le16_to_cpu(id->acoustic);	id->msrqs          = __le16_to_cpu(id->msrqs);	id->sxfert         = __le16_to_cpu(id->sxfert);	id->sal            = __le16_to_cpu(id->sal);	id->spg            = __le32_to_cpu(id->spg);	id->lba_capacity_2 = __le64_to_cpu(id->lba_capacity_2);	for (i = 0; i < 22; i++)		id->words104_125[i]   = __le16_to_cpu(id->words104_125[i]);	id->last_lun       = __le16_to_cpu(id->last_lun);	id->word127        = __le16_to_cpu(id->word127);	id->dlf            = __le16_to_cpu(id->dlf);	id->csfo           = __le16_to_cpu(id->csfo);	for (i = 0; i < 26; i++)		id->words130_155[i] = __le16_to_cpu(id->words130_155[i]);	id->word156        = __le16_to_cpu(id->word156);	for (i = 0; i < 3; i++)		id->words157_159[i] = __le16_to_cpu(id->words157_159[i]);	id->cfa_power      = __le16_to_cpu(id->cfa_power);	for (i = 0; i < 14; i++)		id->words161_175[i] = __le16_to_cpu(id->words161_175[i]);	for (i = 0; i < 31; i++)		id->words176_205[i] = __le16_to_cpu(id->words176_205[i]);	for (i = 0; i < 48; i++)		id->words206_254[i] = __le16_to_cpu(id->words206_254[i]);	id->integrity_word  = __le16_to_cpu(id->integrity_word);# else#  error "Please fix <asm/byteorder.h>"# endif#endif}/* * ide_fixstring() cleans up and (optionally) byte-swaps a text string, * removing leading/trailing blanks and compressing internal blanks. * It is primarily used to tidy up the model name/number fields as * returned by the WIN_[P]IDENTIFY commands. */void ide_fixstring (u8 *s, const int bytecount, const int byteswap)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -