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

📄 ide-m8xx.c

📁 em85xx的大硬盘修正代码包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * * *  linux/drivers/ide/ide-m8xx.c * */#include <linux/config.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/stddef.h>#include <linux/unistd.h>#include <linux/ptrace.h>#include <linux/slab.h>#include <linux/user.h>#include <linux/a.out.h>#include <linux/tty.h>#include <linux/major.h>#include <linux/interrupt.h>#include <linux/reboot.h>#include <linux/init.h>#include <linux/blk.h>#include <linux/ioport.h>#include <linux/ide.h>#include <linux/bootmem.h>#include <asm/mpc8xx.h>#include <asm/mmu.h>#include <asm/processor.h>#include <asm/residual.h>#include <asm/io.h>#include <asm/pgtable.h>#include <asm/ide.h>#include <asm/8xx_immap.h>#include <asm/machdep.h>#include <asm/irq.h>#include "ide_modes.h"static int identify  (volatile unsigned char *p);static void print_fixed (volatile unsigned char *p);static void print_funcid (int func);static int check_ide_device (unsigned long base);static void ide_interrupt_ack (void *dev);static void m8xx_ide_tuneproc(ide_drive_t *drive, byte pio);typedef	struct ide_ioport_desc {	unsigned long	base_off;		/* Offset to PCMCIA memory	*/	ide_ioreg_t	reg_off[IDE_NR_PORTS];	/* controller register offsets	*/	int		irq;			/* IRQ				*/} ide_ioport_desc_t;ide_ioport_desc_t ioport_dsc[MAX_HWIFS] = {#ifdef IDE0_BASE_OFFSET	{ IDE0_BASE_OFFSET,	    {		IDE0_DATA_REG_OFFSET,		IDE0_ERROR_REG_OFFSET,		IDE0_NSECTOR_REG_OFFSET,		IDE0_SECTOR_REG_OFFSET,		IDE0_LCYL_REG_OFFSET,		IDE0_HCYL_REG_OFFSET,		IDE0_SELECT_REG_OFFSET,		IDE0_STATUS_REG_OFFSET,		IDE0_CONTROL_REG_OFFSET,		IDE0_IRQ_REG_OFFSET,	    },	    IDE0_INTERRUPT,	},#ifdef IDE1_BASE_OFFSET	{ IDE1_BASE_OFFSET,	    {		IDE1_DATA_REG_OFFSET,		IDE1_ERROR_REG_OFFSET,		IDE1_NSECTOR_REG_OFFSET,		IDE1_SECTOR_REG_OFFSET,		IDE1_LCYL_REG_OFFSET,		IDE1_HCYL_REG_OFFSET,		IDE1_SELECT_REG_OFFSET,		IDE1_STATUS_REG_OFFSET,		IDE1_CONTROL_REG_OFFSET,		IDE1_IRQ_REG_OFFSET,	    },	    IDE1_INTERRUPT,	},#endif /* IDE1_BASE_OFFSET */#endif	/* IDE0_BASE_OFFSET */};ide_pio_timings_t ide_pio_clocks[6];int hold_time[6] =  {30, 20, 15, 10, 10, 10 };   /* PIO Mode 5 with IORDY (nonstandard) *//* * Warning: only 1 (ONE) PCMCIA slot supported here, * which must be correctly initialized by the firmware (PPCBoot). */static int _slot_ = -1;			/* will be read from PCMCIA registers   *//* Make clock cycles and always round up */#define PCMCIA_MK_CLKS( t, T ) (( (t) * ((T)/1000000) + 999U ) / 1000U )/* * IDE stuff. */static intm8xx_ide_default_irq(ide_ioreg_t base){#ifdef CONFIG_BLK_DEV_MPC8xx_IDE	if (base >= MAX_HWIFS)		return 0;	printk("[%d] m8xx_ide_default_irq %d\n",__LINE__,ioport_dsc[base].irq);		return (ioport_dsc[base].irq);#else        return 9;#endif}static ide_ioreg_tm8xx_ide_default_io_base(int index){        return index;}#define M8XX_PCMCIA_CD2(slot)      (0x10000000 >> (slot << 4))#define M8XX_PCMCIA_CD1(slot)      (0x08000000 >> (slot << 4))/* * The TQM850L hardware has two pins swapped! Grrrrgh! */#ifdef	CONFIG_TQM850L#define __MY_PCMCIA_GCRX_CXRESET	PCMCIA_GCRX_CXOE#define __MY_PCMCIA_GCRX_CXOE		PCMCIA_GCRX_CXRESET#else#define __MY_PCMCIA_GCRX_CXRESET	PCMCIA_GCRX_CXRESET#define __MY_PCMCIA_GCRX_CXOE		PCMCIA_GCRX_CXOE#endif#if defined(CONFIG_BLK_DEV_MPC8xx_IDE) && defined(CONFIG_IDE_8xx_PCCARD)#define PCMCIA_SCHLVL IDE0_INTERRUPT	/* Status Change Interrupt Level	*/static int pcmcia_schlvl = PCMCIA_SCHLVL;#endif/* * See include/linux/ide.h for definition of hw_regs_t (p, base) *//* * m8xx_ide_init_hwif_ports for a direct IDE interface _using_ */#if defined(CONFIG_IDE_8xx_PCCARD) || defined(CONFIG_IDE_8xx_DIRECT)static voidm8xx_ide_init_hwif_ports(hw_regs_t *hw, ide_ioreg_t data_port, 		ide_ioreg_t ctrl_port, int *irq){	ide_ioreg_t *p = hw->io_ports;	int i;	typedef struct {		ulong br;		ulong or;	} pcmcia_win_t;	volatile pcmcia_win_t *win;	volatile pcmconf8xx_t *pcmp;	uint *pgcrx;	u32 pcmcia_phy_base;	u32 pcmcia_phy_end;	static unsigned long pcmcia_base = 0;	unsigned long base;	*p = 0;	if (irq)		*irq = 0;	pcmp = (pcmconf8xx_t *)(&(((immap_t *)IMAP_ADDR)->im_pcmcia));	if (!pcmcia_base) {                /*                 * Read out PCMCIA registers. Since the reset values                 * are undefined, we sure hope that they have been                 * set up by firmware		 */		/* Scan all registers for valid settings */		pcmcia_phy_base = 0xFFFFFFFF;		pcmcia_phy_end = 0;		/* br0 is start of brX and orX regs */		win = (pcmcia_win_t *) \			(&(((immap_t *)IMAP_ADDR)->im_pcmcia.pcmc_pbr0));		for (i = 0; i < 8; i++) {			if (win->or & 1) {	/* This bank is marked as valid */				if (win->br < pcmcia_phy_base) {					pcmcia_phy_base = win->br;				}				if ((win->br + PCMCIA_MEM_SIZE) > pcmcia_phy_end) {					pcmcia_phy_end  = win->br + PCMCIA_MEM_SIZE;				}				/* Check which slot that has been defined */				_slot_ = (win->or >> 2) & 1;			}					/* Valid bank */			win++;		}						/* for */		printk ("PCMCIA slot %c: phys mem %08x...%08x (size %08x)\n",			'A' + _slot_,			pcmcia_phy_base, pcmcia_phy_end,			pcmcia_phy_end - pcmcia_phy_base);		pcmcia_base=(unsigned long)ioremap(pcmcia_phy_base,						   pcmcia_phy_end-pcmcia_phy_base);#ifdef DEBUG		printk ("PCMCIA virt base: %08lx\n", pcmcia_base);#endif		/* Compute clock cycles for PIO timings */		for (i=0; i<6; ++i) {			bd_t	*binfo = (bd_t *)__res;			hold_time[i]   =				PCMCIA_MK_CLKS (hold_time[i],						binfo->bi_busfreq);			ide_pio_clocks[i].setup_time  =				PCMCIA_MK_CLKS (ide_pio_timings[i].setup_time,						binfo->bi_busfreq);			ide_pio_clocks[i].active_time =				PCMCIA_MK_CLKS (ide_pio_timings[i].active_time,						binfo->bi_busfreq);			ide_pio_clocks[i].cycle_time  =				PCMCIA_MK_CLKS (ide_pio_timings[i].cycle_time,						binfo->bi_busfreq);#if 0			printk ("PIO mode %d timings: %d/%d/%d => %d/%d/%d\n",				i,				ide_pio_clocks[i].setup_time,				ide_pio_clocks[i].active_time,				ide_pio_clocks[i].hold_time,				ide_pio_clocks[i].cycle_time,				ide_pio_timings[i].setup_time,				ide_pio_timings[i].active_time,				ide_pio_timings[i].hold_time,				ide_pio_timings[i].cycle_time);#endif		}	}	if (data_port >= MAX_HWIFS)		return;	if (_slot_ == -1) {		printk ("PCMCIA slot has not been defined! Using A as default\n");		_slot_ = 0;	}#ifdef CONFIG_IDE_8xx_PCCARD#ifdef DEBUG	printk ("PIPR = 0x%08X  slot %c ==> mask = 0x%X\n",		pcmp->pcmc_pipr,		'A' + _slot_,		M8XX_PCMCIA_CD1(_slot_) | M8XX_PCMCIA_CD2(_slot_) );#endif /* DEBUG */	if (pcmp->pcmc_pipr & (M8XX_PCMCIA_CD1(_slot_)|M8XX_PCMCIA_CD2(_slot_))) {		printk ("No card in slot %c: PIPR=%08x\n",			'A' + _slot_, (u32) pcmp->pcmc_pipr);		return;		/* No card in slot */	}	check_ide_device (pcmcia_base);#endif	/* CONFIG_IDE_8xx_PCCARD */	base = pcmcia_base + ioport_dsc[data_port].base_off;#ifdef DEBUG	printk ("base: %08x + %08x = %08x\n",			pcmcia_base, ioport_dsc[data_port].base_off, base);#endif	for (i = 0; i < IDE_NR_PORTS; ++i) {#ifdef DEBUG		printk ("port[%d]: %08x + %08x = %08x\n",			i,			base,			ioport_dsc[data_port].reg_off[i],			i, base + ioport_dsc[data_port].reg_off[i]);#endif	 	*p++ = base + ioport_dsc[data_port].reg_off[i];	}	if (irq) {#ifdef CONFIG_IDE_8xx_PCCARD		unsigned int reg;		*irq = ioport_dsc[data_port].irq;		if (_slot_)			pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcrb;		else			pgcrx = &((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pgcra;		reg = *pgcrx;		reg |= mk_int_int_mask (pcmcia_schlvl) << 24;		reg |= mk_int_int_mask (pcmcia_schlvl) << 16;		*pgcrx = reg;#else	/* direct connected IDE drive, i.e. external IRQ, not the PCMCIA irq */		*irq = ioport_dsc[data_port].irq;#endif	/* CONFIG_IDE_8xx_PCCARD */	}	/* register routine to tune PIO mode */	ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc;	hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack;	/* Enable Harddisk Interrupt,	 * and make it edge sensitive	 */	/* (11-18) Set edge detect for irq, no wakeup from low power mode */	((immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel |=					(0x80000000 >> ioport_dsc[data_port].irq);#ifdef CONFIG_IDE_8xx_PCCARD	/* Make sure we dont get garbage irq */	((immap_t *) IMAP_ADDR)->im_pcmcia.pcmc_pscr = 0xFFFF;	/* Enable falling edge irq */	pcmp->pcmc_per = 0x100000 >> (16 * _slot_);#endif	/* CONFIG_IDE_8xx_PCCARD */}	/* m8xx_ide_init_hwif_ports() using 8xx internal PCMCIA interface */#endif /* CONFIG_IDE_8xx_PCCARD || CONFIG_IDE_8xx_DIRECT *//* * m8xx_ide_init_hwif_ports for a direct IDE interface _not_ using * MPC8xx's internal PCMCIA interface */#if defined(CONFIG_IDE_EXT_DIRECT)void m8xx_ide_init_hwif_ports (hw_regs_t *hw,	ide_ioreg_t data_port, ide_ioreg_t ctrl_port, int *irq){	ide_ioreg_t *p = hw->io_ports;	int i;	u32 ide_phy_base;	u32 ide_phy_end;	static unsigned long ide_base = 0;	unsigned long base;	*p = 0;	if (irq)		*irq = 0;	if (!ide_base) {		/* TODO:		 * - add code to read ORx, BRx		 */		ide_phy_base = CFG_ATA_BASE_ADDR;		ide_phy_end  = CFG_ATA_BASE_ADDR + 0x200;		printk ("IDE phys mem : %08x...%08x (size %08x)\n",			ide_phy_base, ide_phy_end,			ide_phy_end - ide_phy_base);				ide_base=(unsigned long)ioremap(ide_phy_base,						ide_phy_end-ide_phy_base);#ifdef DEBUG		printk ("IDE virt base: %08lx\n", ide_base);#endif	}	if (data_port >= MAX_HWIFS)		return;	base = ide_base + ioport_dsc[data_port].base_off;#ifdef DEBUG	printk ("base: %08x + %08x = %08x\n",		ide_base, ioport_dsc[data_port].base_off, base);#endif	for (i = 0; i < IDE_NR_PORTS; ++i) {#ifdef DEBUG		printk ("port[%d]: %08x + %08x = %08x\n",			i,			base,			ioport_dsc[data_port].reg_off[i],			i, base + ioport_dsc[data_port].reg_off[i]);#endif	 	*p++ = base + ioport_dsc[data_port].reg_off[i];	}	if (irq) {		/* direct connected IDE drive, i.e. external IRQ */		*irq = ioport_dsc[data_port].irq;	}	/* register routine to tune PIO mode */	ide_hwifs[data_port].tuneproc = m8xx_ide_tuneproc;	hw->ack_intr = (ide_ack_intr_t *) ide_interrupt_ack;	/* Enable Harddisk Interrupt,	 * and make it edge sensitive	 */	/* (11-18) Set edge detect for irq, no wakeup from low power mode */	((immap_t *) IMAP_ADDR)->im_siu_conf.sc_siel |=			(0x80000000 >> ioport_dsc[data_port].irq);}	/* m8xx_ide_init_hwif_ports() for CONFIG_IDE_8xx_DIRECT */ #endif	/* CONFIG_IDE_8xx_DIRECT *//* -------------------------------------------------------------------- *//* PCMCIA Timing */#ifndef	PCMCIA_SHT#define PCMCIA_SHT(t)	((t & 0x0F)<<16)	/* Strobe Hold  Time 	*/#define PCMCIA_SST(t)	((t & 0x0F)<<12)	/* Strobe Setup Time	*/#define PCMCIA_SL(t) ((t==32) ? 0 : ((t & 0x1F)<<7)) /* Strobe Length	*/#endif

⌨️ 快捷键说明

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