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

📄 sys_eiger.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
字号:
/* *	linux/arch/alpha/kernel/sys_eiger.c * *	Copyright (C) 1995 David A Rusling *	Copyright (C) 1996, 1999 Jay A Estabrook *	Copyright (C) 1998, 1999 Richard Henderson *	Copyright (C) 1999 Iain Grant * * Code supporting the EIGER (EV6+TSUNAMI). */#include <linux/kernel.h>#include <linux/types.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/pci.h>#include <linux/init.h>#include <asm/ptrace.h>#include <asm/system.h>#include <asm/dma.h>#include <asm/irq.h>#include <asm/bitops.h>#include <asm/mmu_context.h>#include <asm/io.h>#include <asm/pci.h>#include <asm/pgtable.h>#include <asm/core_tsunami.h>#include <asm/hwrpb.h>#include "proto.h"#include "irq_impl.h"#include "pci_impl.h"#include "machvec_impl.h"/* Note that this interrupt code is identical to TAKARA.  *//* Note mask bit is true for DISABLED irqs.  */static unsigned long cached_irq_mask[2] = { -1, -1 };static inline voideiger_update_irq_hw(unsigned long irq, unsigned long mask){	int regaddr;	mask = (irq >= 64 ? mask << 16 : mask >> ((irq - 16) & 0x30));	regaddr = 0x510 + (((irq - 16) >> 2) & 0x0c);	outl(mask & 0xffff0000UL, regaddr);}static inline voideiger_enable_irq(unsigned int irq){	unsigned long mask;	mask = (cached_irq_mask[irq >= 64] &= ~(1UL << (irq & 63)));	eiger_update_irq_hw(irq, mask);}static voideiger_disable_irq(unsigned int irq){	unsigned long mask;	mask = (cached_irq_mask[irq >= 64] |= 1UL << (irq & 63));	eiger_update_irq_hw(irq, mask);}static unsigned inteiger_startup_irq(unsigned int irq){	eiger_enable_irq(irq);	return 0; /* never anything pending */}static voideiger_end_irq(unsigned int irq){	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))		eiger_enable_irq(irq);}static struct hw_interrupt_type eiger_irq_type = {	typename:	"EIGER",	startup:	eiger_startup_irq,	shutdown:	eiger_disable_irq,	enable:		eiger_enable_irq,	disable:	eiger_disable_irq,	ack:		eiger_disable_irq,	end:		eiger_end_irq,};static voideiger_device_interrupt(unsigned long vector, struct pt_regs * regs){	unsigned intstatus;	/*	 * The PALcode will have passed us vectors 0x800 or 0x810,	 * which are fairly arbitrary values and serve only to tell	 * us whether an interrupt has come in on IRQ0 or IRQ1. If	 * it's IRQ1 it's a PCI interrupt; if it's IRQ0, it's	 * probably ISA, but PCI interrupts can come through IRQ0	 * as well if the interrupt controller isn't in accelerated	 * mode.	 *	 * OTOH, the accelerator thing doesn't seem to be working	 * overly well, so what we'll do instead is try directly	 * examining the Master Interrupt Register to see if it's a	 * PCI interrupt, and if _not_ then we'll pass it on to the	 * ISA handler.	 */	intstatus = inw(0x500) & 15;	if (intstatus) {		/*		 * This is a PCI interrupt. Check each bit and		 * despatch an interrupt if it's set.		 */		if (intstatus & 8) handle_irq(16+3, regs);		if (intstatus & 4) handle_irq(16+2, regs);		if (intstatus & 2) handle_irq(16+1, regs);		if (intstatus & 1) handle_irq(16+0, regs);	} else {		isa_device_interrupt(vector, regs);	}}static voideiger_srm_device_interrupt(unsigned long vector, struct pt_regs * regs){	int irq = (vector - 0x800) >> 4;	handle_irq(irq, regs);}static void __initeiger_init_irq(void){	long i;	outb(0, DMA1_RESET_REG);	outb(0, DMA2_RESET_REG);	outb(DMA_MODE_CASCADE, DMA2_MODE_REG);	outb(0, DMA2_MASK_REG);	if (alpha_using_srm)		alpha_mv.device_interrupt = eiger_srm_device_interrupt;	for (i = 16; i < 128; i += 16)		eiger_update_irq_hw(i, -1);	init_i8259a_irqs();	for (i = 16; i < 128; ++i) {		irq_desc[i].status = IRQ_DISABLED | IRQ_LEVEL;		irq_desc[i].handler = &eiger_irq_type;	}}static int __initeiger_map_irq(struct pci_dev *dev, u8 slot, u8 pin){	u8 irq_orig;	/* The SRM console has already calculated out the IRQ value's for	   option cards. As this works lets just read in the value already	   set and change it to a useable value by Linux.	   All the IRQ values generated by the console are greater than 90,	   so we subtract 80 because it is (90 - allocated ISA IRQ's).  */	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq_orig);	return irq_orig - 0x80;}static u8 __initeiger_swizzle(struct pci_dev *dev, u8 *pinp){	struct pci_controler *hose = dev->sysdata;	int slot, pin = *pinp;	int bridge_count = 0;	/* Find the number of backplane bridges.  */	int backplane = inw(0x502) & 0x0f;	switch (backplane)	{	   case 0x00: bridge_count = 0; break; /* No bridges */	   case 0x01: bridge_count = 1; break; /* 1 */	   case 0x03: bridge_count = 2; break; /* 2 */	   case 0x07: bridge_count = 3; break; /* 3 */	   case 0x0f: bridge_count = 4; break; /* 4 */	};	/*  Check first for the built-in bridges on hose 0. */	if (hose->index == 0	    && PCI_SLOT(dev->bus->self->devfn) > 20-bridge_count) {		slot = PCI_SLOT(dev->devfn);	} else {		/* Must be a card-based bridge.  */		do {			/* Check for built-in bridges on hose 0. */			if (hose->index == 0			    && (PCI_SLOT(dev->bus->self->devfn)				> 20 - bridge_count)) {                  		slot = PCI_SLOT(dev->devfn);				break;			}			pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));			/* Move up the chain of bridges.  */			dev = dev->bus->self;			/* Slot of the next bridge.  */			slot = PCI_SLOT(dev->devfn);		} while (dev->bus->self);	}	*pinp = pin;	return slot;}/* * The System Vectors */struct alpha_machine_vector eiger_mv __initmv = {	vector_name:		"Eiger",	DO_EV6_MMU,	DO_DEFAULT_RTC,	DO_TSUNAMI_IO,	DO_TSUNAMI_BUS,	machine_check:		tsunami_machine_check,	max_dma_address:	ALPHA_MAX_DMA_ADDRESS,	min_io_address:		DEFAULT_IO_BASE,	min_mem_address:	DEFAULT_MEM_BASE,	nr_irqs:		128,	device_interrupt:	eiger_device_interrupt,	init_arch:		tsunami_init_arch,	init_irq:		eiger_init_irq,	init_rtc:		common_init_rtc,	init_pci:		common_init_pci,	kill_arch:		tsunami_kill_arch,	pci_map_irq:		eiger_map_irq,	pci_swizzle:		eiger_swizzle,};ALIAS_MV(eiger)

⌨️ 快捷键说明

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