📄 ide.c
字号:
/* * Copyright (c) 2004-2005 Atmark Techno, Inc. All Rights Reserved. */#include <ep93xx/regmap.h>#include <ep93xx/regs_syscon.h>#include <ep93xx/regs_ide.h>#include <ep93xx/regs_smc.h>#include <target/io.h>#define MULTIPLE 3#define TIMEOUT 50000#define inb(addr) (*(volatile unsigned char *)(addr))#define inw(addr) (*(volatile unsigned short *)(addr))#define inl(addr) (*(volatile unsigned long *)(addr))#define outb(b,addr) (*(volatile unsigned char *)(addr)=(b))#define outw(w,addr) (*(volatile unsigned short *)(addr)=(w))#define outl(l,addr) (*(volatile unsigned long *)(addr)=(l))static int (*ide_init) (void);static unsigned char (*ide_inb) (unsigned int addr);static unsigned short (*ide_inw) (unsigned int addr);static void (*ide_outb) (unsigned char b, unsigned int addr);static void (*ide_outw) (unsigned short w, unsigned int addr);#define delay(count) {int d;for(d=0;d<(count*MULTIPLE);d++){__asm__ volatile ("nop");};}static int _ide_init(void){ unsigned int uiTemp; /* * Make sure the GPIO on IDE bits in the DEVCFG register are not set. */ uiTemp = inl(SYSCON_DEVCFG) & ~(SYSCON_DEVCFG_EonIDE | SYSCON_DEVCFG_GonIDE | SYSCON_DEVCFG_HonIDE); SysconSetLocked( SYSCON_DEVCFG, uiTemp ); /* * Make sure that MWDMA and UDMA are disabled. */ outl(0, IDEMDMAOP); outl(0, IDEUDMAOP); /* * Set up the IDE interface for PIO transfers, using the default PIO * mode. */ outl(IDECfg_IDEEN | IDECfg_PIO | (4 << IDECfg_MODE_SHIFT) | (1 << IDECfg_WST_SHIFT), IDECFG); return 0;}static unsigned char _ide_inb (unsigned int addr){ unsigned int uiIDECR; /* * Write the address out. */ uiIDECR = IDECtrl_DIORn | IDECtrl_DIOWn | ((addr & 7) << 2) | (addr >> 10); outl(uiIDECR, IDECR); /* * Toggle the read signal. */ outl(uiIDECR & ~IDECtrl_DIORn, IDECR); outl(uiIDECR, IDECR); /* * Read the data in. */ return(inl(IDEDATAIN) & 0xff);}static unsigned short _ide_inw (unsigned int addr){ unsigned int uiIDECR; /* * Write the address out. */ uiIDECR = IDECtrl_DIORn | IDECtrl_DIOWn | ((addr & 7) << 2) | (addr >> 10); outl(uiIDECR, IDECR); /* * Toggle the read signal. */ outl(uiIDECR & ~IDECtrl_DIORn, IDECR); outl(uiIDECR, IDECR); /* * Read the data in. */ return(inl(IDEDATAIN) & 0xffff);}static void _ide_outb (unsigned char b, unsigned int addr){ unsigned int uiIDECR; /* * Write the address out. */ uiIDECR = IDECtrl_DIORn | IDECtrl_DIOWn | ((addr & 7) << 2) | (addr >> 10); outl(uiIDECR, IDECR); /* * Write the data out. */ outl(b, IDEDATAOUT); /* * Toggle the write signal. */ outl(uiIDECR & ~IDECtrl_DIOWn, IDECR); outl(uiIDECR, IDECR);}static void _ide_outw (unsigned short w, unsigned int addr){ unsigned int uiIDECR; /* * Write the address out. */ uiIDECR = IDECtrl_DIORn | IDECtrl_DIOWn | ((addr & 7) << 2) | (addr >> 10); outl(uiIDECR, IDECR); /* * Write the data out. */ outl(w, IDEDATAOUT); /* * Toggle the write signal. */ outl(uiIDECR & ~IDECtrl_DIOWn, IDECR); outl(uiIDECR, IDECR);}/* * CIS Tupel codes */#define CISTPL_NULL 0x00#define CISTPL_DEVICE 0x01#define CISTPL_LONGLINK_CB 0x02#define CISTPL_INDIRECT 0x03#define CISTPL_CONFIG_CB 0x04#define CISTPL_CFTABLE_ENTRY_CB 0x05#define CISTPL_LONGLINK_MFC 0x06#define CISTPL_BAR 0x07#define CISTPL_PWR_MGMNT 0x08#define CISTPL_EXTDEVICE 0x09#define CISTPL_CHECKSUM 0x10#define CISTPL_LONGLINK_A 0x11#define CISTPL_LONGLINK_C 0x12#define CISTPL_LINKTARGET 0x13#define CISTPL_NO_LINK 0x14#define CISTPL_VERS_1 0x15#define CISTPL_ALTSTR 0x16#define CISTPL_DEVICE_A 0x17#define CISTPL_JEDEC_C 0x18#define CISTPL_JEDEC_A 0x19#define CISTPL_CONFIG 0x1a#define CISTPL_CFTABLE_ENTRY 0x1b#define CISTPL_DEVICE_OC 0x1c#define CISTPL_DEVICE_OA 0x1d#define CISTPL_DEVICE_GEO 0x1e#define CISTPL_DEVICE_GEO_A 0x1f#define CISTPL_MANFID 0x20#define CISTPL_FUNCID 0x21#define CISTPL_FUNCE 0x22#define CISTPL_SWIL 0x23#define CISTPL_END 0xff/* * CIS Function ID codes */#define CISTPL_FUNCID_MULTI 0x00#define CISTPL_FUNCID_MEMORY 0x01#define CISTPL_FUNCID_SERIAL 0x02#define CISTPL_FUNCID_PARALLEL 0x03#define CISTPL_FUNCID_FIXED 0x04#define CISTPL_FUNCID_VIDEO 0x05#define CISTPL_FUNCID_NETWORK 0x06#define CISTPL_FUNCID_AIMS 0x07#define CISTPL_FUNCID_SCSI 0x08/* * Fixed Disk FUNCE codes */#define CISTPL_IDE_INTERFACE 0x01#define CISTPL_FUNCE_IDE_IFACE 0x01#define CISTPL_FUNCE_IDE_MASTER 0x02#define CISTPL_FUNCE_IDE_SLAVE 0x03/* First feature byte */#define CISTPL_IDE_SILICON 0x04#define CISTPL_IDE_UNIQUE 0x08#define CISTPL_IDE_DUAL 0x10/* Second feature byte */#define CISTPL_IDE_HAS_SLEEP 0x01#define CISTPL_IDE_HAS_STANDBY 0x02#define CISTPL_IDE_HAS_IDLE 0x04#define CISTPL_IDE_LOW_POWER 0x08#define CISTPL_IDE_REG_INHIBIT 0x10#define CISTPL_IDE_HAS_INDEX 0x20#define CISTPL_IDE_IOIS16 0x40#define MAX_TUPEL_SZ 512#define MAX_FEATURES 4typedef unsigned char u8;typedef unsigned short u16;typedef unsigned long u32;static int pcmcia_check_ide_device (unsigned long base){ volatile u8 *ident = 0; volatile u8 *feature_p[MAX_FEATURES]; volatile u8 *p, *start; int n_features = 0; u8 func_id = ~0; u8 code, len; unsigned short config_base = 0; int found = 0; start = p = (volatile u8 *) base; while ((p - start) < MAX_TUPEL_SZ) { code = *p; p += 2; if (code == 0xFF) { /* End of chain */ break; } len = *p; p += 2; switch (code) { case CISTPL_VERS_1: ident = p + 4; break; case CISTPL_FUNCID: func_id = *p; break; case CISTPL_FUNCE: if (n_features < MAX_FEATURES) feature_p[n_features++] = p; break; case CISTPL_CONFIG: config_base = (*(p+6) << 8) + (*(p+4)); default: break; } p += 2 * len; } if (func_id != ((u8)~0)) { if (func_id == CISTPL_FUNCID_FIXED) found = 1; else { return (1); /* no disk drive */ } } if (!found) { return (1); } /* set level mode irq and I/O mapped device in config reg*/ *((u8 *)(base + config_base + 6)) = 0x0; *((u8 *)(base + config_base + 0)) = 0x41; *((u8 *)(base + config_base + 2)) = 0x0; *((u8 *)(base + config_base + 4)) = 0x0; return (0);}#define PCMCIA_BASE_PHYS 0x40000000#define PCMCIA_ADDR_MEM (PCMCIA_BASE_PHYS + 0xC000000)#define PCMCIA_ADDR_ATTR (PCMCIA_BASE_PHYS + 0x8000000)#define PCMCIA_ADDR_IO (PCMCIA_BASE_PHYS)#define PCMCIA_WP 0x01#define PCMCIA_CD1 0x02#define PCMCIA_CD2 0x04#define PCMCIA_BVD1 0x08#define PCMCIA_BVD2 0x10#define PCMCIA_VS1 0x20#define PCMCIA_RDY 0x40#define PCMCIA_VS2 0x80static int pcmcia_ide_init (void){ unsigned long ulPFDR; unsigned long ulTemp; outl( inl(GPIO_PADR) | 0x8, GPIO_PADR ); //Power off delay (300000); ulTemp = inl(GPIO_FINTEN); outl( ulTemp & ~(PCMCIA_RDY | PCMCIA_CD1 | PCMCIA_CD2 | PCMCIA_BVD2 | PCMCIA_BVD1), GPIO_FINTEN); ulTemp = inl(GPIO_FINTEN); ulTemp = inl(GPIO_PFDDR); outl( ulTemp & ~(PCMCIA_RDY | PCMCIA_CD1 | PCMCIA_CD2 | PCMCIA_BVD2 | PCMCIA_BVD1), GPIO_PFDDR); ulTemp = inl(GPIO_PFDDR); ulTemp = inl(GPIO_FDB); outl( (ulTemp & ~(PCMCIA_RDY | PCMCIA_BVD2 | PCMCIA_BVD1)) | PCMCIA_CD1 | PCMCIA_CD2, GPIO_FDB ); ulTemp = inl(GPIO_FINTTYPE1); outl( (ulTemp & ~PCMCIA_RDY) | PCMCIA_CD1 | PCMCIA_CD2 | PCMCIA_BVD2 | PCMCIA_BVD1, GPIO_FINTTYPE1 ); ulTemp = inl(GPIO_FINTTYPE2); outl( ulTemp & ~(PCMCIA_RDY | PCMCIA_CD1 | PCMCIA_CD2 | PCMCIA_BVD2 | PCMCIA_BVD1), GPIO_FINTTYPE2 ); ulTemp = inl(GPIO_FINTTYPE2); outl( PCMCIA_RDY | PCMCIA_CD1 | PCMCIA_CD2 | PCMCIA_BVD2 | PCMCIA_BVD1, GPIO_FEOI ); ulTemp = inl(GPIO_FEOI); outl( 0x800a0405, SMC_PCIO ); ulTemp = inl(SMC_PCIO); outl( 0x110403, SMC_PCAttribute ); ulTemp = inl(SMC_PCAttribute); outl( 0x110403, SMC_PCCommon ); ulTemp = inl(SMC_PCCommon); ulTemp = (inl(SMC_PCMCIACtrl) | PCCONT_WEN | PCCONT_PC1EN) & ~PCCONT_PC1RST; outl( ulTemp, SMC_PCMCIACtrl ); ulTemp = inl(SMC_PCMCIACtrl); ulTemp = inl(GPIO_FINTEN); outl( (ulTemp & ~(PCMCIA_CD1 | PCMCIA_CD2 | PCMCIA_BVD2 | PCMCIA_BVD1)) | PCMCIA_RDY, GPIO_FINTEN ); ulTemp = inl(GPIO_FINTEN); ulPFDR = inl(GPIO_PFDR); if (ulPFDR & (PCMCIA_CD1 | PCMCIA_CD2)) { return -1; /* No card in slot */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -