📄 pcan_main.c
字号:
//----------------------------------------------------------------------------// search all pci based devices from peakstatic int search_and_create_pci_devices(void){ int result = 0; struct pcandev *dev = NULL; // search pci devices DPRINTK(KERN_DEBUG "%s: search_and_create_pci_devices()\n", DEVICE_NAME); if (pci_present()) { struct pci_dev *pciDev; struct pci_dev *from = NULL; do { pciDev = pci_find_device((unsigned int)PCAN_PCI_VENDOR_ID, (unsigned int)PCAN_PCI_DEVICE_ID, from); if (pciDev != NULL) { u16 wSubSysID; // a PCI device with PCAN_PCI_VENDOR_ID and PCAN_PCI_DEVICE_ID was found from = pciDev; // get the PCI Subsystem-ID result = pci_read_config_word(pciDev, 0x2E, &wSubSysID); if (result) goto fail; // configure the PCI chip, part 1 result = pci_write_config_word(pciDev, 0x04, 2); if (result) goto fail; result = pci_write_config_word(pciDev, 0x44, 0); if (result) goto fail; wmb(); // make the first device on board if ((dev = (struct pcandev *)kmalloc(sizeof(struct pcandev), GFP_KERNEL)) == NULL) goto fail; pcan_soft_init(dev, "pci", HW_PCI); #ifdef LINUX_24 result = pcan_pci_init(dev, (u32)pciDev->resource[0].start, (u32)pciDev->resource[1].start, (u16)pciDev->irq, (wSubSysID > 3) ? CHANNEL_MASTER : CHANNEL_SINGLE, NULL); #endif #ifdef LINUX_22 result = pcan_pci_init(dev, (u32)pciDev->base_address[0], (u32)pciDev->base_address[1], (u16)pciDev->irq, (wSubSysID > 3) ? CHANNEL_MASTER : CHANNEL_SINGLE, NULL); #endif if (!result) result = sja1000_probe(dev); if (result) { dev->cleanup(dev); kfree(dev); goto fail; } else { dev->ucPhysicallyInstalled = 1; list_add_tail(&dev->list, &pcan_drv.devices); // add this device to the list pcan_drv.wDeviceCount++; } if (wSubSysID > 3) { struct pcandev *master_dev = dev; // make the second device on board if ((dev = (struct pcandev *)kmalloc(sizeof(struct pcandev), GFP_KERNEL)) == NULL) goto fail; pcan_soft_init(dev, "pci", HW_PCI); #ifdef LINUX_24 result = pcan_pci_init(dev, (u32)pciDev->resource[0].start, (u32)pciDev->resource[1].start + 0x400, (u16)pciDev->irq, CHANNEL_SLAVE, master_dev); #endif #ifdef LINUX_22 result = pcan_pci_init(dev, (u32)pciDev->base_address[0], (u32)pciDev->base_address[1] + 0x400, (u16)pciDev->irq, CHANNEL_SLAVE, master_dev); #endif if (!result) result = sja1000_probe(dev); if (result) { dev->cleanup(dev); kfree(dev); goto fail; } else { dev->ucPhysicallyInstalled = 1; list_add_tail(&dev->list, &pcan_drv.devices); // add this device to the list pcan_drv.wDeviceCount++; } } } } while (pciDev != NULL); } DPRINTK(KERN_DEBUG "%s: search_and_create_pci_devices() is OK\n", DEVICE_NAME); fail: return result; }//----------------------------------------------------------------------------// create all declared isa devicesstatic int create_isa_devices(void){ int result = 0; int i; struct pcandev *dev = NULL; // create isa devices DPRINTK(KERN_DEBUG "%s: create_isa_devices()\n", DEVICE_NAME); for (i = 0; ((i < 8) && (type[i] != NULL)); i++) { if (!strncmp(type[i], "isa", 4)) { if ((dev = (struct pcandev *)kmalloc(sizeof(struct pcandev), GFP_KERNEL)) == NULL) goto fail; pcan_soft_init(dev, type[i], HW_ISA_SJA); result = pcan_isa_init(dev, (u32)io[i], (u16)irq[i]); if (!result) result = sja1000_probe(dev); if (result) { dev->cleanup(dev); kfree(dev); goto fail; } else { dev->ucPhysicallyInstalled = 1; list_add_tail(&dev->list, &pcan_drv.devices); // add this device to the list pcan_drv.wDeviceCount++; } } } DPRINTK(KERN_DEBUG "%s: create_isa_devices() is OK\n", DEVICE_NAME); fail: return result;}//----------------------------------------------------------------------------// create all declared dongle devicesstatic int create_dongle_devices(void){ int result = 0; int i; struct pcandev *dev = NULL; DPRINTK(KERN_DEBUG "%s: create_dongle_devices()\n", DEVICE_NAME); for (i = 0; ((i < 8) && (type[i] != NULL)); i++) { if (!strncmp(type[i], "sp", 4) || !strncmp(type[i], "epp", 4)) { if ((dev = (struct pcandev *)kmalloc(sizeof(struct pcandev), GFP_KERNEL)) == NULL) goto fail; pcan_soft_init(dev, type[i], (!strncmp(type[i], "sp", 4)) ? HW_DONGLE_SJA : HW_DONGLE_SJA_EPP); result = pcan_dongle_init(dev, (u32)io[i], (u16)irq[i], type[i]); if (result) { dev->cleanup(dev); kfree(dev); goto fail; } else { list_add_tail(&dev->list, &pcan_drv.devices); // add this device to the list pcan_drv.wDeviceCount++; } } } DPRINTK(KERN_DEBUG "%s: create_dongle_devices() is OK\n", DEVICE_NAME); fail: return result; }#ifdef USB_SUPPORT//----------------------------------------------------------------------------// init for usb based devices from peakstatic int register_usb_devices(void){ int err; DPRINTK(KERN_DEBUG "%s: register_usb_devices()\n", DEVICE_NAME); if (!(err = pcan_usb_init())) { DPRINTK(KERN_DEBUG "%s: register_usb_devices() is OK\n", DEVICE_NAME); } return err;}#endif#ifdef LINUX_22//----------------------------------------------------------------------------// replacement for kernel 2.4.x function// original from sysdep.h from the book// "Linux Device Drivers" by Alessandro Rubini and Jonathan Corbet, published by O'Reilly & Associates.static struct proc_dir_entry *create_proc_read_entry(const char *name, mode_t mode, struct proc_dir_entry *base, read_proc_t *read_proc, void * data){ struct proc_dir_entry *res = create_proc_entry(name, mode, base); if (res) { res->read_proc=read_proc; res->data=data; } return res;}#endif//----------------------------------------------------------------------------// is called when the device is installed 'insmod pcan.o'int init_module(void){ int result = 0; pcan_drv.wInitStep = 0; pcan_drv.dwInitTime = get_mtime(); // store time for timestamp relation, increments in msec pcan_drv.szVersionString = CURRENT_RELEASE; // get the release name global printk(KERN_INFO "%s: %s\n", DEVICE_NAME, pcan_drv.szVersionString); INIT_LIST_HEAD(&pcan_drv.devices); pcan_drv.wDeviceCount = 0; // search pci devices if ((result = search_and_create_pci_devices())) goto fail; // create isa devices if ((result = create_isa_devices())) goto fail; // create dongle devices if ((result = create_dongle_devices())) goto fail; #ifdef USB_SUPPORT // register usb devices only if ((result = register_usb_devices())) goto fail; #else // no device found, stop all if (!pcan_drv.wDeviceCount) goto fail; #endif pcan_drv.wInitStep = 1; // register the driver by the OS pcan_drv.nMajor = PCAN_MAJOR; if ((result = register_chrdev(pcan_drv.nMajor, DEVICE_NAME, &pcan_fops)) < 0) goto fail; if (!pcan_drv.nMajor) pcan_drv.nMajor = result; pcan_drv.wInitStep = 2; // create the proc entry if (create_proc_read_entry(DEVICE_NAME, 0, NULL, pcan_read_procmem, NULL) == NULL) { result = -ENODEV; // maybe wrong if there is no proc filesystem configured goto fail; } pcan_drv.wInitStep = 3; printk(KERN_INFO "%s: major %d.\n", DEVICE_NAME, pcan_drv.nMajor); return 0; // succeed fail: cleanup_module(); return result;}// end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -