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

📄 ide.c

📁 1. 8623L平台
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Mambo Hard Disk Device Driver for PC  * * by Ho Lee 2003/06/12 */#include <linux/kernel.h>#include <linux/module.h>#include <linux/string.h>#include <linux/delay.h>#include <asm/byteorder.h>#include <linux/hdreg.h>/*#ifdef CONFIG_MODVERSIONS#define MODVERSIONS#include <linux/modversions.h>#endif*/#include "mum.h"#include "mambo.h"#include "ide.h"// #define IDE_VERBOSE			1//// IDE registers// #define IDE_DATA_OFFSET		(0)#define IDE_ERROR_OFFSET	(1)#define IDE_NSECTOR_OFFSET	(2)#define IDE_SECTOR_OFFSET	(3)#define IDE_LCYL_OFFSET		(4)#define IDE_HCYL_OFFSET		(5)#define IDE_SELECT_OFFSET	(6)#define IDE_STATUS_OFFSET	(7)#define IDE_DATA_REG		(MAMBO_IDE_BASE + (IDE_DATA_OFFSET << 2))#define IDE_ERROR_REG		(MAMBO_IDE_BASE + (IDE_ERROR_OFFSET << 2))#define IDE_NSECTOR_REG		(MAMBO_IDE_BASE + (IDE_NSECTOR_OFFSET << 2))#define IDE_SECTOR_REG		(MAMBO_IDE_BASE + (IDE_SECTOR_OFFSET << 2))#define IDE_LCYL_REG		(MAMBO_IDE_BASE + (IDE_LCYL_OFFSET << 2))#define IDE_HCYL_REG		(MAMBO_IDE_BASE + (IDE_HCYL_OFFSET << 2))#define IDE_SELECT_REG		(MAMBO_IDE_BASE + (IDE_SELECT_OFFSET << 2))#define IDE_STATUS_REG		(MAMBO_IDE_BASE + (IDE_STATUS_OFFSET << 2))#define IDE_FEATURE_REG		IDE_ERROR_REG#define IDE_COMMAND_REG		IDE_STATUS_REG// ATA/ATAPI commands#define WIN_NOP				0x00#define WIN_DEVICE_RESET	0x08#define WIN_READ			0x20 /* 28-Bit */#define WIN_WRITE			0x30 /* 28-Bit */#define WIN_FORMAT			0x50#define WIN_SEEK			0x70#define WIN_DIAGNOSE		0x90#define WIN_PIDENTIFY		0xA1 #define WIN_READDMA			0xC8 /* read sectors using DMA transfers */#define WIN_WRITEDMA		0xCA /* write sectors using DMA transfers */#define WIN_IDENTIFY		0xEC#define WIN_SETFEATURES		0xEF /* set special drive features *//* WIN_SETFEATURES sub-commands */#define SETFEATURES_XFER	0x03	/* Set transfer mode */#	define XFER_UDMA_7		0x47	/* 0100|0111 */#	define XFER_UDMA_6		0x46	/* 0100|0110 */#	define XFER_UDMA_5		0x45	/* 0100|0101 */#	define XFER_UDMA_4		0x44	/* 0100|0100 */#	define XFER_UDMA_3		0x43	/* 0100|0011 */#	define XFER_UDMA_2		0x42	/* 0100|0010 */#	define XFER_UDMA_1		0x41	/* 0100|0001 */#	define XFER_UDMA_0		0x40	/* 0100|0000 */#	define XFER_MW_DMA_2	0x22	/* 0010|0010 */#	define XFER_MW_DMA_1	0x21	/* 0010|0001 */#	define XFER_MW_DMA_0	0x20	/* 0010|0000 */#	define XFER_SW_DMA_2	0x12	/* 0001|0010 */#	define XFER_SW_DMA_1	0x11	/* 0001|0001 */#	define XFER_SW_DMA_0	0x10	/* 0001|0000 */#	define XFER_PIO_4		0x0C	/* 0000|1100 */#	define XFER_PIO_3		0x0B	/* 0000|1011 */#	define XFER_PIO_2		0x0A	/* 0000|1010 */#	define XFER_PIO_1		0x09	/* 0000|1001 */#	define XFER_PIO_0		0x08	/* 0000|1000 */#	define XFER_PIO_SLOW	0x00	/* 0000|0000 */// status#define ERR_STAT			0x01#define INDEX_STAT			0x02#define ECC_STAT			0x04#define DRQ_STAT			0x08#define SEEK_STAT			0x10#define WRERR_STAT			0x20#define READY_STAT			0x40#define BUSY_STAT			0x80//// IDE register I/O//static __inline__ void OUT_BYTE(int drive, unsigned char data, unsigned int port){	mum_writew(IDE_CONTROLLER(drive), (unsigned short) data, port);}static __inline__ void OUT_WORD(int drive, unsigned short data, unsigned int port){	mum_writew(IDE_CONTROLLER(drive), (unsigned short) data, port);}static __inline unsigned char IN_BYTE(int drive, unsigned int port){	unsigned char data = (unsigned char) (mum_readw(IDE_CONTROLLER(drive), port) & 0xff);	return data;}static __inline unsigned short IN_WORD(int drive, unsigned int port){	unsigned short data = (unsigned short) (mum_readw(IDE_CONTROLLER(drive), port));	return data;}//// IDE Initialize//static int g_ide_dsinited = 0;ide_info_t g_ideinfo[MAX_DRIVES];int ide_dsinit(void){	int i;	memset(g_ideinfo, 0, sizeof g_ideinfo);	for (i = 0; i < MAX_DRIVES; ++i)		g_ideinfo[i].select.all = ((IDE_DRIVE(i) << 4) | 0xa0);	g_ide_dsinited = 1;	return 0;}int ide_found(int mask){	int drive, found = 0;	ide_info_t *pideinfo;	if (!g_ide_dsinited)		ide_dsinit();	for (drive = 0; drive < MAX_DRIVES; ++drive) {		pideinfo = g_ideinfo + drive;		if (pideinfo->type & mask) 			found |= (1 << drive);	}	return found;}int ide_probe(int drivemask, int verbose){	int drive, nfound;	ide_info_t *pideinfo;	if (!g_ide_dsinited)		ide_dsinit();	for (drive = 0, nfound = 0; drive < MAX_DRIVES; ++drive) {		if (drivemask & (1 << drive)) {			if (verbose)				printk("Probing drive %d:%d :\n", IDE_CONTROLLER(drive), IDE_DRIVE(drive));						pideinfo = ide_identify(drive);			if (pideinfo->type != IDE_NONE) {				if (verbose) 					printk("  Found %s device : ", (pideinfo->type == IDE_ATA) ? "ATA" : "ATAPI");				else					printk("IDE %d:%d (%s) : ", IDE_CONTROLLER(drive), IDE_DRIVE(drive), 						(pideinfo->type == IDE_ATA) ? "ATA" : "ATAPI");			}						if (pideinfo->type != IDE_NONE) {				++nfound;				printk("%s, %dMB, %s, %s\n", pideinfo->id.model, pideinfo->size, 					pideinfo->lba ? "LBA" : "CHS",					pideinfo->cap_udma ? "UDMA" : (pideinfo->cap_dma ? "DMA" : "No DMA"));				if (!pideinfo->lba && verbose)					printk("  cylinders = %d, heads = %d, sectors = %d\n",						pideinfo->cyls, pideinfo->heads, pideinfo->sectors); 				if (verbose) {					printk("  ");					if (pideinfo->cap_udma)						printk("Ultra DMA = 0x%04x, ", pideinfo->id.dma_ultra);					printk("Multi-word DMA = 0x%04x, Single-word DMA = 0x%04x, PIO = 0x%04x\n",						pideinfo->id.dma_mword, pideinfo->id.dma_1word, pideinfo->id.eide_pio_modes);					printk("  EIDE DMA Min = 0x%04x, EIDE DMA Time = 0x%04x\n",						pideinfo->id.eide_dma_min, pideinfo->id.eide_dma_time);					printk("  PIO mode support :");					if (pideinfo->id.eide_pio_modes & 0x01)						printk(" 3");					if (pideinfo->id.eide_pio_modes & 0x02)						printk(" 4");					printk("\n");					printk("  Major Rev = 0x%04x, Minor Rev = 0x%04x\n",						pideinfo->id.major_rev_num, pideinfo->id.minor_rev_num);					// dump_memory(&pideinfo->id, 0, SECTOR_SIZE, 1);				}				// setup DMA mode				/*				if (pideinfo->id.dma_mword & 0x0f) {					// find the most high DMA mode					for (i = 2; i >= 0; --i) {						if (pideinfo->id.dma_mword & (1 << i)) {							ide_set_drive_speed(drive, XFER_MW_DMA_0 | i);							if (verbose)								printk("  Use Multiword DMA mode %d\n", i);							break;						}					}				}				*/			}		}	}	return nfound;}//// IDE command//static int ide_command(int cmd, int drive, int feature, int cyl, int head, int sector, int nsector, void *buf, int buflen);static int ide_wait_stat(int drive, int mask, int waitmask, int usetimeout);static int ide_select_drive(int drive);static void ide_input_data(int drive, unsigned int *buf, unsigned int wcount);static void ide_output_data(int drive, unsigned int *buf, unsigned int wcount);static void ide_fixstring(unsigned char *s, const int bytecount, const int byteswap);int ide_command(int cmd, int drive, int feature, int cyl, int head, int sector, int nsector, void *buf, int buflen){#if IDE_VERBOSE	static struct {		int cmd;		char *name;	} s_cmdnamelist[] = {		{ WIN_NOP, "NOP" },		{ WIN_DEVICE_RESET, "Device Reset" },		{ WIN_READ, "Read Sector" },		{ WIN_WRITE, "Write Sector" },		{ WIN_FORMAT, "Format Sector" },		{ WIN_SEEK, "Seek" },		{ WIN_DIAGNOSE, "Diagnose" },		{ WIN_PIDENTIFY, "ATAPI Identify" },		{ WIN_READDMA, "Read Sector by DMA" },		{ WIN_WRITEDMA, "Write Sector by DMA" },		{ WIN_IDENTIFY, "ATA Identify" },		{ -1, NULL },	};	int i;#endif		int status;		// Selecting drive#if IDE_VERBOSE	printk("  Select, ");#endif	if (ide_select_drive(drive)) {#if IDE_VERBOSE		printk("No device\n");#endif		return 1;	} 		// Sending command	OUT_BYTE(drive, feature, IDE_FEATURE_REG);	OUT_BYTE(drive, nsector, IDE_NSECTOR_REG);	OUT_BYTE(drive, sector, IDE_SECTOR_REG);	OUT_BYTE(drive, (cyl & 0xff), IDE_LCYL_REG);	OUT_BYTE(drive, (cyl >> 8) & 0xff, IDE_HCYL_REG);	OUT_BYTE(drive, head | g_ideinfo[drive].select.all, IDE_SELECT_REG);	#if IDE_VERBOSE	for (i = 0; s_cmdnamelist[i].cmd >= 0; ++i) {		if (cmd == s_cmdnamelist[i].cmd) {			printk("%s, ", s_cmdnamelist[i].name);			break;		}	}	if (s_cmdnamelist[i].cmd < 0)		printk("Command 0x%02x, ", cmd);#endif	OUT_BYTE(drive, cmd, IDE_COMMAND_REG);	// Reading or Writing data	if (buf && buflen > 0) {		if (cmd == WIN_WRITE) {			while (buflen > 0) {#if IDE_VERBOSE				printk("Writing\n");				if (buflen > SECTOR_SIZE)					printk(", ");				else					printk("\n");#endif				ide_wait_stat(drive, DRQ_STAT, DRQ_STAT, 0);				ide_output_data(drive, (unsigned int *) buf, SECTOR_SIZE / 4);				buf = (unsigned char *) buf + SECTOR_SIZE;				buflen -= SECTOR_SIZE;				ide_wait_stat(drive, BUSY_STAT, 0, 0);			}		} else {			memset(buf, 0, buflen);			while (buflen > 0) {				ide_wait_stat(drive, BUSY_STAT, 0, 0);				status = IN_BYTE(drive, IDE_STATUS_REG);				if (status & DRQ_STAT) {#if IDE_VERBOSE					printk("Reading");					if (buflen > SECTOR_SIZE)						printk(", ");					else						printk("\n");#endif					ide_input_data(drive, (unsigned int *) buf, SECTOR_SIZE / 4);					buf = (unsigned char *) buf + SECTOR_SIZE;					buflen -= SECTOR_SIZE;				} else {#if IDE_VERBOSE					printk("No Data\n");	#endif					return 2;				}			} 		}	} #if IDE_VERBOSE	else		printk("\n");#endif		return 0;}#define IDE_WAIT_TIMEOUT		20000int ide_wait_stat(int drive, int mask, int waitmask, int usetimeout){	int status;	int timeout = IDE_WAIT_TIMEOUT;		do {		status = IN_BYTE(drive, IDE_STATUS_REG);		if (usetimeout) {			if (timeout-- == 0)				return 1;			mdelay(1);		}	} while ((status & mask) != waitmask);

⌨️ 快捷键说明

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