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

📄 ems_pci.c

📁 can4linux-3.5.3.gz can4 linux
💻 C
📖 第 1 页 / 共 2 页
字号:
/* PCI card handling *  * This still is old-style handling * walking through the list of PCI devices manually * This has to be replaced by pci_register_driver() * and the pci_probe function() */#include "defs.h"#include <linux/pci.h>#ifdef CAN4LINUX_PCI# ifndef CONFIG_PCI#   error "trying to compile a PCI driver for a kernel without CONFIG_PCI"# endif#ifdef CAN4LINUX_PCIint Can_RequestIrq(int minor, int irq,#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)     irqreturn_t (*handler)(int, void *))#else    irqreturn_t (*handler)(int, void *, struct pt_regs *))#endif{int err = 0;    DBGin();    /*    int request_irq(unsigned int irq,			// interrupt number                void (*handler)(int, void *, struct pt_regs *), // pointer to ISR		              irq, dev_id, registers on stack              unsigned long irqflags, const char *devname,              void *dev_id);       dev_id - The device ID of this handler (see below).              This parameter is usually set to NULL,       but should be non-null if you wish to do  IRQ  sharing.       This  doesn't  matter when hooking the       interrupt, but is required so  that,  when  free_irq()  is       called,  the  correct driver is unhooked.  Since this is a       void *, it can point to anything (such  as  a  device-spe-       cific  structure,  or even empty space), but make sure you       pass the same pointer to free_irq().    */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)     err = request_irq(irq, handler, IRQF_SHARED, "Can", &Can_minors[minor]);#else    err = request_irq(irq, handler, SA_SHIRQ, "Can", &Can_minors[minor]);#endif    if( !err ){      DBGprint(DBG_BRANCH,("Requested IRQ: %d @ 0x%lx",      				irq, (unsigned long)handler));      IRQ_requested[minor] = 1;    }    DBGout(); return err;}int Can_FreeIrq(int minor, int irq ){    DBGin();    IRQ_requested[minor] = 0;    /* printk(" Free IRQ %d  minor %d\n", irq, minor);  */    free_irq(irq, &Can_minors[minor]);    DBGout();    return 0;}/* * Perform Vendor-Init, that means sometimes CAN controller * or only board manufacturer specific initialization. * * Mainly it gets needed IO and IRQ ressources and initilaizes  * special hardware functions. * */int CAN_VendorInit (int minor){    DBGin();    can_range[minor] = CAN_RANGE;        /* PCI scan for CPC-PCI (or others ) has already remapped the address */    /* printk(" assign address direct\n"); */    can_base[minor] = (void __iomem *)Base[minor];    /* The Interrupt Line is alrady requestes by th PC CARD Services     * (in case of CPC-Card: cpc-card_cs.c)     */     if( IRQ[minor] > 0 && IRQ[minor] > MAX_IRQNUMBER ){        if( Can_RequestIrq( minor, IRQ[minor] , CAN_Interrupt) ) {	     printk("Can[%d]: Can't request IRQ %d \n", minor, IRQ[minor]);	     DBGout(); return -EBUSY;        }    } else {	/* Invalid IRQ number in /proc/.../IRQ */	DBGout(); return -EBUSY;    }    DBGout(); return 0;}/* reset both CAN controllers on the EMS-W黱sche CPC-PCI Board *//* writing to the control range at BAR1 of the PCI board */void reset_CPC_PCI(unsigned long address){unsigned long ptr = (unsigned long)ioremap(address, 32);    writeb(0x01, (void __iomem *)ptr);}/* check memory region if there is a CAN controller*  assume the controller was resetted before testing **  The check for an avaliable controller is difficult !*  After an Hardware Reset (or power on) the Conroller *  is in the so-called 'BasicCAN' mode.*     we can check for: *         adress  name      value*	    0x00  mode       0x21*           0x02  status     0xc0*           0x03  interrupt  0xe0* Once loaded the driver switches into 'PeliCAN' mode and things are getting* difficult, because we now have only a 'soft reset' with not so  unique* values. The values have to be masked before comparing.*         adress  name       mask   value*	    0x00  mode               *           0x01  command    0xff    0x00*           0x02  status     0x37    0x34*           0x03  interrupt  0xfb    0x00**/int controller_available(upointer_t address, int offset){/* unsigned long ptr = (unsigned long)ioremap(address, 32 * offset); */void __iomem *ptr = ioremap(address, CAN_RANGE);#if 0     /* debugging */    printk("controller_available 0x%0lx\n", address);    printk("0x%0x, ", readb(ptr) );    printk("0x%0x, ", readb(ptr + (2 * offset)) );    printk("0x%0x\n", readb(ptr + (3 * offset)) );    /* return 1; */#endif    if ( 0x21 == readb(ptr))  {	/* compare reset values of status and interrupt register */	if(   0x0c == readb(ptr + (2 * offset))	   && 0xe0 == readb(ptr + (3 * offset)) ) {	    return 1;	} else {	    return 0;	}    } else {	/* may be called after a 'soft reset' in 'PeliCAN' mode */	/*   value     address                     mask    */	if(   0x00 ==  readb(ptr + (1 * offset))	   && 0x34 == (readb(ptr + (2 * offset))    & 0x37)	   && 0x00 == (readb(ptr + (3 * offset))    & 0xfb)	  ) {	    return 1;	} else {	    return 0;	}    }}#endif#define PCI_BASE_ADDRESS0(dev) (dev->resource[0].start)#define PCI_BASE_ADDRESS1(dev) (dev->resource[1].start)#define PCI_BASE_ADDRESS2(dev) (dev->resource[2].start)#define PCI_BASE_ADDRESS3(dev) (dev->resource[3].start)/* used for storing the global pci register address */upointer_t Can_pitapci_control[MAX_CHANNELS];# if defined(CPC_PCI)#ifndef PCI_DEVICE_ID_PLX_9030#define PCI_DEVICE_ID_PLX_9030 0x9030#endif#if 0static struct pci_device_id  ems_pci_tbl[] = {      { PCI_DEVICE(PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9030), },      { 0, },                 /* End of list */};#endifint register_new_cpcpci(struct pci_dev *pdev, int i){void __iomem *ptr;		/* ptr to PCI control registers*/void __iomem *cptr;		/* ptr to start of CAN control registers*/int j;				/* loop through possible CAN controllers */int minor = -1;			/* to make DBGin() happy */    DBGin();    	                 /* dev, bar, size */    ptr		= pci_iomap(pdev, 0, 128);    cptr	= pci_iomap(pdev, 2, 2048);    printk("cptr= %p \n", cptr);    /* look for a CAN controllers starting at 0x400 */    for(j = 0; j < 4; j++) {   	if(controller_available(PCI_BASE_ADDRESS2(pdev) 					+ 0x400 + (0x200 * j), 1)) {	    err(" CAN controller %d. at pos %d\n", i + 1, j);	    if(i > MAX_CHANNELS) {		err("only %d devices supported\n", MAX_CHANNELS);		break; /* the devices scan loop */	    }	    IOModel[i]	= 'm';	    IRQ[i]	= pdev->irq;	    Base[i]	= (upointer_t) cptr + 0x400 + (0x200 * j);#ifdef __x86_64__	    err("Base %llx/%lld", Base[i], Base[i]);#else	    err("Base %lx", Base[i]);#endif	    Can_pitapci_control[i] = (upointer_t)ptr;/* store pointer to control reg */	    i++;	}    }    /* enable IRQ in PLX 9030 */    writel(PLX9030_ICR_ENABLE_IRQ0, ptr + PLX9030_ICR);    DBGout();    return i;	/* returns last CAN controller number found */}/* check if the pci device is a valid old style CPC-PCI and gett all the hardware information nneded and fill in the board informationthe device itself is already registered  pci_enable_device()*/int register_old_cpcpci(struct pci_dev *pdev, int i){unsigned long ptr;		/* ptr to PITA control */int minor = -1;			/* to make DBGin() happy */    DBGin();    err("int i ist %d", i);    ptr = (unsigned long)ioremap(PCI_BASE_ADDRESS0(pdev), 256);    /* enable memory access */    /* printk("write to pita\n"); */    writel(PITA2_MISC_CONFIG, (void __iomem *)ptr + PITA2_MISC);    Can_pitapci_control[i] = ptr;    /* printk("        pita ptr %lx\n", ptr); */    /* printk("---------------\n"); */    /* dump_CAN(PCI_BASE_ADDRESS1(pdev)+0x400, 4); */    /* printk("---------------\n"); */    /* dump_CAN(PCI_BASE_ADDRESS1(pdev)+0x600, 4); */    /* PCI_BASE_ADDRESS1:     * at address 0 are some EMS control registers

⌨️ 快捷键说明

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