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

📄 pci-sd0001.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *   $Id: pci-sd0001.c,v 1.1.2.1 2003/06/24 08:40:50 dwmw2 Exp $ * *   linux/arch/sh/kernel/pci-sd0001.c * *   Support Hitachi Semcon SD0001 SH3 PCI Host Bridge . *   * *   Copyright (C) 2000  Hitachi ULSI Systems Co., Ltd. *   All Rights Reserved. * *   Copyright (C) 2001-2003 Red Hat, Inc. * *   Authors:	Masayuki Okada (macha@adc.hitachi-ul.co.jp) *              David Woodhouse (dwmw2@redhat.com) * * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2, or (at your option) *   any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include <linux/init.h>#include <linux/pci.h>#include <linux/kernel.h>#include <linux/irq.h>#include <linux/interrupt.h>#include <linux/spinlock.h>#include <linux/delay.h>#include <linux/vmalloc.h>#include <asm/pci.h>#include <asm/io.h>#include <asm/irq.h>#include "pci-sd0001.h"spinlock_t sd0001_indirect_lock = SPIN_LOCK_UNLOCKED;int remap_area_pages(unsigned long address, unsigned long phys_addr,                     unsigned long size, unsigned long flags);#undef DEBUG#ifdef DEBUG#define DBG(x...) printk(x)#else#define DBG(x...)#endif#define SD0001_INDIR_TIME	1000000		/* 粗儡アクセス窗位略ち呵络搀眶 */static char *err_int_msg [] = {	"Detect Master Abort",	"Assert Master Abort",	"Detect Target Abort",	"Assert Target Abort",	"Assert PERR",	"Detect PERR",	"Detect SERR",	"Asster SERR",	"Bus Timeout",	"Bus Retry Over",};/* * PCIバスのバスリセット悸乖 */static void sd0001_bus_reset(void){	sd0001_writel(SD0001_RST_BUSRST, RESET);	udelay(64);	sd0001_writel(0, RESET);}/* * SD0001ソフトリセット */static void sd0001_chip_reset(void){	sd0001_writel(SD0001_RST_SWRST, RESET);}#define ROUND_UP(x, a)		(((x) + (a) - 1) & ~((a) - 1))static voidsd0001_int_pcierr (int irq, void *dummy, struct pt_regs *regs){	static char  errStrings[30*12];	u32 int_status;	u32 mask;	u32 indrct_flg;	int reset_fatal;	int   i;	int   to_cnt = 0;	unsigned long flags;	spin_lock_irqsave(&sd0001_indirect_lock, flags);	if ((int_status = (sd0001_readl(INT_STS1) & SD0001_INT_BUSERR))) {		DBG("pciIntErrorHandle Called: status 0x%08x\n", int_status, 0, 0, 0, 0, 0);		for (mask = 1 << 20, i = 0, errStrings[0] = '\0'; i < 11; i++, mask <<= 1) {			if (int_status & mask) {/* 				err_int_cnt[i] ++; */				strcat(errStrings, err_int_msg[i]);				strcat(errStrings, ", ");			}		}		i = strlen(errStrings);		errStrings[i-2]= '\0';		printk(KERN_ERR "PCI Bus 0x%08x(%s) Error\n", int_status, errStrings);		reset_fatal = 0;		if (int_status & (SD0001_INT_SSERR|SD0001_INT_RPERR				  |SD0001_INT_SPERR|SD0001_INT_STABT				  |SD0001_INT_RTABT|SD0001_INT_RMABT)) {			/* Clear of Configration Status Bits */			sd0001_writel(4, INDIRECT_ADR);			sd0001_writel(0xf9000000, INDIRECT_DATA);			sd0001_writel(0x000c0002, INDIRECT_CTL);			to_cnt = 0;			while (((indrct_flg = sd0001_readl(INDIRECT_STS)) & SD0001_INDRCTF_INDFLG)			       && (to_cnt++ < SD0001_INDIR_TIME))				;			if (indrct_flg & SD0001_INDRCTF_INDFLG) {				panic("SD0001 Fatal Error 1\n");			} else {				if (indrct_flg & SD0001_INDRCTF_MABTRCV) {					sd0001_writel(SD0001_INDRCTC_FLGRESET, INDIRECT_CTL);					reset_fatal = -1;				}			}			int_status = sd0001_readl(INT_STS1) & SD0001_INT_BUSERR;		}		if (int_status != 0) {			sd0001_writel(int_status, INT_STS1); /* 充り哈みクリア */			if (reset_fatal || (sd0001_readl(INT_STS2) & SD0001_INT_BUSERR)) {				printk(KERN_CRIT "Fatal Error:SD0001 PCI Status Can't Clear 0x%08x\n",				       int_status & 0x7fffffff);				sd0001_writel(sd0001_readl(INT_ENABLE) & ~int_status, INT_ENABLE);				/* Masked Error Interrupt */			}		}	}	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);}static inline u32 convert_dev_to_addr (struct pci_dev *dev, u32 reg){	return (SD0001_CONFIG_ADDR_EN		| (dev->bus->number << 16)		| ((dev->devfn & 0xff) << 8)		| (reg & 0xff)		| ((dev->bus->number)?0x00:0x01));}static int sd0001_indirect_RW (u32  addr, u32 cmd, u32  be,				  u32  rw, u32  *data){	u32 indrct_flg;	u32 int_sts;	u32 to_cnt = 0;	int st = PCIBIOS_SUCCESSFUL;	unsigned long flags;	spin_lock_irqsave(&sd0001_indirect_lock, flags);	if ((cmd & SD0001_INDRCTC_CMD_MASK) == SD0001_INDRCTC_CMD_MEMR	    || (cmd & SD0001_INDRCTC_CMD_MASK) == SD0001_INDRCTC_CMD_MEMW)		sd0001_writel(addr & 0xfffffffc, INDIRECT_ADR);	else		sd0001_writel(addr, INDIRECT_ADR);	if (rw == SD0001_INDRCTC_IOWT || rw == SD0001_INDRCTC_COWT)		sd0001_writel(*data, INDIRECT_DATA);	sd0001_writel(be | cmd | rw , INDIRECT_CTL);	while (((indrct_flg = sd0001_readl(INDIRECT_STS)) & SD0001_INDRCTF_INDFLG)	       && (to_cnt++ < SD0001_INDIR_TIME));	int_sts = sd0001_readl(INT_STS1) & SD0001_INT_BUSERR;    	if (indrct_flg & SD0001_INDRCTF_INDFLG) {	/* タイムアウト */		printk("SD0001 Fatal Error 2\n");		spin_unlock_irqrestore(&sd0001_indirect_lock, flags);		return PCIBIOS_DEVICE_NOT_FOUND;	}	if (int_sts != 0 || (indrct_flg & SD0001_INDRCTF_MABTRCV) != 0) {		if ((st = (indrct_flg & SD0001_INDRCTF_MABTRCV) >> 19) != 0) {			sd0001_writel(SD0001_INDRCTC_FLGRESET, INDIRECT_CTL);			st |= 0x80000000;		}		st |= 0x80000000 | int_sts;		if ((int_sts & (SD0001_INT_SSERR|SD0001_INT_RPERR				|SD0001_INT_SPERR|SD0001_INT_STABT				|SD0001_INT_RTABT|SD0001_INT_RMABT))		    || (indrct_flg & SD0001_INDRCTF_MABTRCV)) {			/* Clear of Configration Status Bits */			sd0001_writel(4, INDIRECT_ADR);			sd0001_writel(0xf9000000, INDIRECT_DATA);			sd0001_writel(0x000c0002, INDIRECT_CTL);			to_cnt = 0;			while (((indrct_flg = sd0001_readl(INDIRECT_STS)) & SD0001_INDRCTF_INDFLG)			       && (to_cnt++ < SD0001_INDIR_TIME));			if (indrct_flg & SD0001_INDRCTF_INDFLG) {	/* タイムアウト */				panic("SD0001 Fatal Error 3\n");			}			if (indrct_flg & SD0001_INDRCTF_MABTRCV) {								sd0001_writel(SD0001_INDRCTC_FLGRESET, INDIRECT_CTL);			}		}				printk(KERN_ERR "PCI Bus Error: status 0x%08x\n", st);		if ((int_sts = sd0001_readl(INT_STS1) & SD0001_INT_BUSERR) != 0) {			sd0001_writel(int_sts, INT_STS1);	/* 充り哈みクリア */						if (sd0001_readl(INT_STS2) & SD0001_INT_BUSERR) {				printk(KERN_CRIT "Fatal Error:SD0001 PCI Status Can't Clear 0x%08x\n",				       sd0001_readl(INT_STS2) & SD0001_INT_BUSERR);				sd0001_writel(sd0001_readl(INT_ENABLE) & ~int_sts, INT_ENABLE); /* Masked Error Interrupt */			}		}		*data = 0xffffffff;	} else {		if (rw != SD0001_INDRCTC_IOWT && rw != SD0001_INDRCTC_COWT)			*data = sd0001_readl(INDIRECT_DATA);	}	spin_unlock_irqrestore(&sd0001_indirect_lock, flags);	return st;}static inlineint sd0001_config_RW (struct pci_dev *dev, u32 reg, u32 be, u32 rw, u32 *data){	u32  reg_addr = convert_dev_to_addr(dev, reg);	if (reg_addr == 0) {		*data = 0xffffffff;		return PCIBIOS_SUCCESSFUL;	}    	return sd0001_indirect_RW (reg_addr, 0, be, rw, data);}static int sd0001_read_config_byte(struct pci_dev *dev, int reg, u8 *val){	int  offset;	u32  be;	int  re;	union {		u32 ldata;		u8  bdata[4];	} work;	be = SD0001_INDRCTC_BE_BYTE << (reg & 0x03);	re = sd0001_config_RW (dev, reg, be, SD0001_INDRCTC_CORD, &work.ldata);#if __LITTLE_ENDIAN__	offset = reg & 0x03;#else  /* __LITTLE_ENDIAN__ */	offset = 3 - (reg & 0x03);#endif /* __LITTLE_ENDIAN__ */	*val = work.bdata[offset];	return re;}static int sd0001_read_config_word(struct pci_dev *dev, int reg, u16 *val){	int  offset;	u32 be;	int  re;	union {		u32 ldata;		u16 wdata[2];	} work;	be = SD0001_INDRCTC_BE_WORD << (reg & 0x02);		re = sd0001_config_RW (dev, reg, be, SD0001_INDRCTC_CORD, &work.ldata);	#if __LITTLE_ENDIAN__	offset = (reg >> 1) & 0x01;#else  /* __LITTLE_ENDIAN__ */	offset = 1 - ((reg >> 1) & 0x01);#endif /* __LITTLE_ENDIAN__ */		*val = work.wdata[offset];		return re;}static int sd0001_read_config_dword(struct pci_dev *dev, int reg, u32 *val){	return sd0001_config_RW (dev, reg, SD0001_INDRCTC_BE_LONG,			      SD0001_INDRCTC_CORD, val);}static int sd0001_write_config_byte (struct pci_dev *dev, int reg, u8 val){	int  offset;	u32 be;	union {		u32 ldata;		u8  bdata[4];	} work;	be = SD0001_INDRCTC_BE_BYTE << (reg & 0x03);#if __LITTLE_ENDIAN__	offset = reg & 0x03;#else  /* __LITTLE_ENDIAN__ */	offset = 3 - (reg & 0x03);#endif /* __LITTLE_ENDIAN__ */	work.bdata[offset] = val;	return sd0001_config_RW(dev, reg, be, SD0001_INDRCTC_COWT, &work.ldata);    }static int sd0001_write_config_word (struct pci_dev *dev, int reg, u16 val){	int  offset;	u32 be;	union {		u32  ldata;		u16  wdata[2];	} work;	be = SD0001_INDRCTC_BE_WORD << (reg & 0x02);#if __LITTLE_ENDIAN__	offset = (reg >> 1) & 0x01;#else  /* __LITTLE_ENDIAN__ */	offset = 1 - ((reg >> 1) & 0x01);#endif /* __LITTLE_ENDIAN__ */	work.wdata[offset] = val;	return sd0001_config_RW (dev, reg, be, SD0001_INDRCTC_COWT, &work.ldata);}static int sd0001_write_config_dword (struct pci_dev *dev, int reg, u32 val){	return sd0001_config_RW (dev, reg, SD0001_INDRCTC_BE_LONG, SD0001_INDRCTC_COWT, &val);}static struct pci_ops sd0001_pci_ops = {	.read_byte =	sd0001_read_config_byte,	.read_word =	sd0001_read_config_word,	.read_dword =	sd0001_read_config_dword,	.write_byte =	sd0001_write_config_byte,	.write_word =	sd0001_write_config_word,	.write_dword =	sd0001_write_config_dword};int __init pci_setup_sd0001 (void)

⌨️ 快捷键说明

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