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

📄 pcic.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
		if ((flags & IORESOURCE_IO) != 0) {			if (address < 0x10000) {				/*				 * A device responds to I/O cycles on PCI.				 * We generate these cycles with memory				 * access into the fixed map (phys 0x30000000).				 *				 * Since a device driver does not want to				 * do ioremap() before accessing PC-style I/O,				 * we supply virtual, ready to access address.				 *				 * Ebus devices do not come here even if				 * CheerIO makes a similar conversion.				 * See ebus.c for details.				 *				 * Note that check_region()/request_region()				 * work for these devices.				 *				 * XXX Neat trick, but it's a *bad* idea				 * to shit into regions like that.				 * What if we want to allocate one more				 * PCI base address...				 */				dev->resource[j].start =				    pcic->pcic_io + address;				dev->resource[j].end = 1;  /* XXX */				dev->resource[j].flags =				    (flags & ~IORESOURCE_IO) | IORESOURCE_MEM;			} else {				/*				 * OOPS... PCI Spec allows this. Sun does				 * not have any devices getting above 64K				 * so it must be user with a weird I/O				 * board in a PCI slot. We must remap it				 * under 64K but it is not done yet. XXX				 */				printk("PCIC: Skipping I/O space at 0x%lx,"				    "this will Oops if a driver attaches;"				    "device '%s' at %02x:%02x)\n", address,				    namebuf, dev->bus->number, dev->devfn);			}		}	}}static voidpcic_fill_irq(struct linux_pcic *pcic, struct pci_dev *dev, int node){	struct pcic_ca2irq *p;	int i, ivec;	char namebuf[64];	if (node == 0 || node == -1) {		strcpy(namebuf, "???");	} else {		prom_getstring(node, "name", namebuf, sizeof(namebuf));	}	if ((p = pcic->pcic_imap) == 0) {		dev->irq = 0;		return;	}	for (i = 0; i < pcic->pcic_imdim; i++) {		if (p->busno == dev->bus->number && p->devfn == dev->devfn)			break;		p++;	}	if (i >= pcic->pcic_imdim) {		printk("PCIC: device %s devfn %02x:%02x not found in %d\n",		    namebuf, dev->bus->number, dev->devfn, pcic->pcic_imdim);		dev->irq = 0;		return;	}	i = p->pin;	if (i >= 0 && i < 4) {		ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO);		dev->irq = ivec >> (i << 2) & 0xF;	} else if (i >= 4 && i < 8) {		ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);		dev->irq = ivec >> ((i-4) << 2) & 0xF;	} else {					/* Corrupted map */		printk("PCIC: BAD PIN %d\n", i); for (;;) {}	}/* P3 */ /* printk("PCIC: device %s pin %d ivec 0x%x irq %x\n", namebuf, i, ivec, dev->irq); */	/*	 * dev->irq=0 means PROM did not bother to program the upper	 * half of PCIC. This happens on JS-E with PROM 3.11, for instance.	 */	if (dev->irq == 0 || p->force) {		if (p->irq == 0 || p->irq >= 15) {	/* Corrupted map */			printk("PCIC: BAD IRQ %d\n", p->irq); for (;;) {}		}		printk("PCIC: setting irq %d at pin %d for device %02x:%02x\n",		    p->irq, p->pin, dev->bus->number, dev->devfn);		dev->irq = p->irq;		i = p->pin;		if (i >= 4) {			ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);			ivec &= ~(0xF << ((i - 4) << 2));			ivec |= p->irq << ((i - 4) << 2);			writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_HI);		} else {			ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO);			ivec &= ~(0xF << (i << 2));			ivec |= p->irq << (i << 2);			writew(ivec, pcic->pcic_regs+PCI_INT_SELECT_LO);		} 	}	return;}/* * Normally called from {do_}pci_scan_bus... */void __init pcibios_fixup_bus(struct pci_bus *bus){	struct list_head *walk;	int i, has_io, has_mem;	unsigned short cmd;	struct linux_pcic *pcic;	/* struct linux_pbm_info* pbm = &pcic->pbm; */	int node;	struct pcidev_cookie *pcp;	if (!pcic0_up) {		printk("pcibios_fixup_bus: no PCIC\n");		return;	}	pcic = &pcic0;	/*	 * Next crud is an equivalent of pbm = pcic_bus_to_pbm(bus);	 */	if (bus->number != 0) {		printk("pcibios_fixup_bus: nonzero bus 0x%x\n", bus->number);		return;	}	walk = &bus->devices;	for (walk = walk->next; walk != &bus->devices; walk = walk->next) {		struct pci_dev *dev = pci_dev_b(walk);		/*		 * Comment from i386 branch:		 *     There are buggy BIOSes that forget to enable I/O and memory		 *     access to PCI devices. We try to fix this, but we need to		 *     be sure that the BIOS didn't forget to assign an address		 *     to the device. [mj]		 * OBP is a case of such BIOS :-)		 */		has_io = has_mem = 0;		for(i=0; i<6; i++) {			unsigned long f = dev->resource[i].flags;			if (f & IORESOURCE_IO) {				has_io = 1;			} else if (f & IORESOURCE_MEM)				has_mem = 1;		}		pcic_read_config_word(dev, PCI_COMMAND, &cmd);		if (has_io && !(cmd & PCI_COMMAND_IO)) {			printk("PCIC: Enabling I/O for device %02x:%02x\n",				dev->bus->number, dev->devfn);			cmd |= PCI_COMMAND_IO;			pcic_write_config_word(dev, PCI_COMMAND, cmd);		}		if (has_mem && !(cmd & PCI_COMMAND_MEMORY)) {			printk("PCIC: Enabling memory for device %02x:%02x\n",				dev->bus->number, dev->devfn);			cmd |= PCI_COMMAND_MEMORY;			pcic_write_config_word(dev, PCI_COMMAND, cmd);		}    		node = pdev_to_pnode(&pcic->pbm, dev);		if(node == 0)			node = -1;		/* cookies */		pcp = pci_devcookie_alloc();		pcp->pbm = &pcic->pbm;		pcp->prom_node = node;		dev->sysdata = pcp;		/* fixing I/O to look like memory */		if ((dev->class>>16) != PCI_BASE_CLASS_BRIDGE)			pcic_map_pci_device(pcic, dev, node);		pcic_fill_irq(pcic, dev, node);	}}/* * pcic_pin_to_irq() is exported to ebus.c. */unsigned intpcic_pin_to_irq(unsigned int pin, char *name){	struct linux_pcic *pcic = &pcic0;	unsigned int irq;	unsigned int ivec;	if (pin < 4) {		ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_LO);		irq = ivec >> (pin << 2) & 0xF;	} else if (pin < 8) {		ivec = readw(pcic->pcic_regs+PCI_INT_SELECT_HI);		irq = ivec >> ((pin-4) << 2) & 0xF;	} else {					/* Corrupted map */		printk("PCIC: BAD PIN %d FOR %s\n", pin, name);		for (;;) {}	/* XXX Cannot panic properly in case of PROLL */	}/* P3 */ /* printk("PCIC: dev %s pin %d ivec 0x%x irq %x\n", name, pin, ivec, irq); */	return irq;}/* Makes compiler happy */static volatile int pcic_timer_dummy;static void pcic_clear_clock_irq(void){	pcic_timer_dummy = readl(pcic0.pcic_regs+PCI_SYS_LIMIT);}static void pcic_timer_handler (int irq, void *h, struct pt_regs *regs){	pcic_clear_clock_irq();	do_timer(regs);}#define USECS_PER_JIFFY  10000  /* We have 100HZ "standard" timer for sparc */#define TICK_TIMER_LIMIT ((100*1000000/4)/100)void __init pci_time_init(void){	struct linux_pcic *pcic = &pcic0;	unsigned long v;	int timer_irq, irq;	/* A hack until do_gettimeofday prototype is moved to arch specific headers	   and btfixupped. Patch do_gettimeofday with ba pci_do_gettimeofday; nop */	((unsigned int *)do_gettimeofday)[0] = 	    0x10800000 | ((((unsigned long)pci_do_gettimeofday -	     (unsigned long)do_gettimeofday) >> 2) & 0x003fffff);	((unsigned int *)do_gettimeofday)[1] = 0x01000000;	BTFIXUPSET_CALL(bus_do_settimeofday, pci_do_settimeofday, BTFIXUPCALL_NORM);	btfixup();	writel (TICK_TIMER_LIMIT, pcic->pcic_regs+PCI_SYS_LIMIT);	/* PROM should set appropriate irq */	v = readb(pcic->pcic_regs+PCI_COUNTER_IRQ);	timer_irq = PCI_COUNTER_IRQ_SYS(v);	writel (PCI_COUNTER_IRQ_SET(timer_irq, 0),		pcic->pcic_regs+PCI_COUNTER_IRQ);	irq = request_irq(timer_irq, pcic_timer_handler,			  (SA_INTERRUPT | SA_STATIC_ALLOC), "timer", NULL);	if (irq) {		prom_printf("time_init: unable to attach IRQ%d\n", timer_irq);		prom_halt();	}	__sti();}static __inline__ unsigned long do_gettimeoffset(void){	struct tasklet_struct *t;	unsigned long offset = 0;	/* 	 * We devide all to 100	 * to have microsecond resolution and to avoid overflow	 */	unsigned long count = 	    readl(pcic0.pcic_regs+PCI_SYS_COUNTER) & ~PCI_SYS_COUNTER_OVERFLOW;	count = ((count/100)*USECS_PER_JIFFY) / (TICK_TIMER_LIMIT/100);	t = &bh_task_vec[TIMER_BH];	if (test_bit(TASKLET_STATE_SCHED, &t->state))		offset = 1000000;	return offset + count;}extern volatile unsigned long wall_jiffies;static void pci_do_gettimeofday(struct timeval *tv){ 	unsigned long flags;	save_and_cli(flags);	*tv = xtime;	tv->tv_usec += do_gettimeoffset();	/*	 * xtime is atomically updated in timer_bh. The difference	 * between jiffies and wall_jiffies is nonzero if the timer	 * bottom half hasnt executed yet.	 */	if ((jiffies - wall_jiffies) != 0)		tv->tv_usec += USECS_PER_JIFFY;	restore_flags(flags);	if (tv->tv_usec >= 1000000) {		tv->tv_usec -= 1000000;		tv->tv_sec++;	}       }static void pci_do_settimeofday(struct timeval *tv){	cli();	tv->tv_usec -= do_gettimeoffset();	if(tv->tv_usec < 0) {		tv->tv_usec += 1000000;		tv->tv_sec--;	}	xtime = *tv;	time_adjust = 0;		/* stop active adjtime() */	time_status |= STA_UNSYNC;	time_maxerror = NTP_PHASE_LIMIT;	time_esterror = NTP_PHASE_LIMIT;	sti();}#if 0static void watchdog_reset() {	writeb(0, pcic->pcic_regs+PCI_SYS_STATUS);}#endif/* * Other archs parse arguments here. */char * __init pcibios_setup(char *str){	return str;}/* */void pcibios_update_resource(struct pci_dev *pdev, struct resource *res1,			     struct resource *res2, int index){}void pcibios_align_resource(void *data, struct resource *res, unsigned long size){}int pcibios_enable_device(struct pci_dev *pdev){	return 0;}/* * NMI */void pcic_nmi(unsigned int pend, struct pt_regs *regs){	pend = flip_dword(pend);	if (!pcic_speculative || (pend & PCI_SYS_INT_PENDING_PIO) == 0) {		/*		 * XXX On CP-1200 PCI #SERR may happen, we do not know		 * what to do about it yet.		 */		printk("Aiee, NMI pend 0x%x pc 0x%x spec %d, hanging\n",		    pend, (int)regs->pc, pcic_speculative);		for (;;) { }	}	pcic_speculative = 0;	pcic_trapped = 1;	regs->pc = regs->npc;	regs->npc += 4;}static inline unsigned long get_irqmask(int irq_nr){	return 1 << irq_nr;}static inline char *pcic_irq_itoa(unsigned int irq){	static char buff[16];	sprintf(buff, "%d", irq);	return buff;}static void pcic_disable_irq(unsigned int irq_nr){	unsigned long mask, flags;	mask = get_irqmask(irq_nr);	save_and_cli(flags);	writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);	restore_flags(flags);}static void pcic_enable_irq(unsigned int irq_nr){	unsigned long mask, flags;	mask = get_irqmask(irq_nr);	save_and_cli(flags);	writel(mask, pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);	restore_flags(flags);}static void pcic_clear_profile_irq(int cpu){	printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__);}static void pcic_load_profile_irq(int cpu, unsigned int limit){	printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__);}/* We assume the caller is local cli()'d when these are called, or else * very bizarre behavior will result. */static void pcic_disable_pil_irq(unsigned int pil){	writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_SET);}static void pcic_enable_pil_irq(unsigned int pil){	writel(get_irqmask(pil), pcic0.pcic_regs+PCI_SYS_INT_TARGET_MASK_CLEAR);}void __init sun4m_pci_init_IRQ(void){	BTFIXUPSET_CALL(enable_irq, pcic_enable_irq, BTFIXUPCALL_NORM);	BTFIXUPSET_CALL(disable_irq, pcic_disable_irq, BTFIXUPCALL_NORM);	BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM);	BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM);	BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM);	BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM);	BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM);	BTFIXUPSET_CALL(__irq_itoa, pcic_irq_itoa, BTFIXUPCALL_NORM);}int pcibios_assign_resource(struct pci_dev *pdev, int resource){	return -ENXIO;}/* * This probably belongs here rather than ioport.c because * we do not want this crud linked into SBus kernels. * Also, think for a moment about likes of floppy.c that * include architecture specific parts. They may want to redefine ins/outs. * * We do not use horroble macroses here because we want to * advance pointer by sizeof(size). */void outsb(unsigned long addr, const void *src, unsigned long count) {	while (count) {		count -= 1;		writeb(*(const char *)src, addr);		src += 1;		addr += 1;	}}void outsw(unsigned long addr, const void *src, unsigned long count) {	while (count) {		count -= 2;		writew(*(const short *)src, addr);		src += 2;		addr += 2;	}}void outsl(unsigned long addr, const void *src, unsigned long count) {	while (count) {		count -= 4;		writel(*(const long *)src, addr);		src += 4;		addr += 4;	}}void insb(unsigned long addr, void *dst, unsigned long count) {	while (count) {		count -= 1;		*(unsigned char *)dst = readb(addr);		dst += 1;		addr += 1;	}}void insw(unsigned long addr, void *dst, unsigned long count) {	while (count) {		count -= 2;		*(unsigned short *)dst = readw(addr);		dst += 2;		addr += 2;	}}void insl(unsigned long addr, void *dst, unsigned long count) {	while (count) {		count -= 4;		/*		 * XXX I am sure we are in for an unaligned trap here.		 */		*(unsigned long *)dst = readl(addr);		dst += 4;		addr += 4;	}}#endif

⌨️ 快捷键说明

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