QUOTE: |
int pcidata_read_proc(char *buf, char **start, off_t offset, int len, int *eof,void *data) { int i, pos = 0; int bus, devfn; if (!pcibios_present()) return sprintf(buf, "No PCI bios present\n"); /* * This code is derived from "drivers/pci/pci.c". This means that * the GPL applies to this source file and credit is due to the * original authors (Drew Eckhardt, Frederic Potter, David * Mosberger-Tang) */ for (bus = 0; !bus; bus++) { /* only bus 0 :-) */ for (devfn = 0; devfn 其中使用的pci_find_slot()函數定義為: struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn) { struct pci_dev *pptr = kmalloc(sizeof(*pptr), GFP_KERNEL); int index = 0; unsigned short vendor; int ret; if (!pptr) return NULL; pptr->index = index; /* 0 */ ret = pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor); if (ret /* == PCIBIOS_DEVICE_NOT_FOUND or whatever error */ || vendor==0xffff || vendor==0x0000) { kfree(pptr); return NULL; } printk("ok (%i, %i %x)\n", bus, devfn, vendor); /* fill other fields */ pptr->bus = bus; pptr->devfn = devfn; pcibios_read_config_word(pptr->bus, pptr->devfn,PCI_VENDOR_ID, &pptr->vendor); pcibios_read_config_word(pptr->bus, pptr->devfn,PCI_DEVICE_ID, &pptr->device); return pptr; } |
QUOTE: |
int pcidata_read_proc(char *buf, char **start, off_t offset, int len, int *eof,void *data) { int i, pos = 0; int bus, devfn; if (!pcibios_present()) return sprintf(buf, "No PCI bios present\n"); /* * This code is derived from "drivers/pci/pci.c". This means that * the GPL applies to this source file and credit is due to the * original authors (Drew Eckhardt, Frederic Potter, David * Mosberger-Tang) */ for (bus = 0; !bus; bus++) { /* only bus 0 :-) */ for (devfn = 0; devfn 其中使用的pci_find_slot()函數定義為: struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn) { struct pci_dev *pptr = kmalloc(sizeof(*pptr), GFP_KERNEL); int index = 0; unsigned short vendor; int ret; if (!pptr) return NULL; pptr->index = index; /* 0 */ ret = pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor); if (ret /* == PCIBIOS_DEVICE_NOT_FOUND or whatever error */ || vendor==0xffff || vendor==0x0000) { kfree(pptr); return NULL; } printk("ok (%i, %i %x)\n", bus, devfn, vendor); /* fill other fields */ pptr->bus = bus; pptr->devfn = devfn; pcibios_read_config_word(pptr->bus, pptr->devfn,PCI_VENDOR_ID, &pptr->vendor); pcibios_read_config_word(pptr->bus, pptr->devfn,PCI_DEVICE_ID, &pptr->device); return pptr; } |
QUOTE: |
static void handle_mtdblock_request(void) { struct request *req; struct mtdblk_dev *mtdblk; unsigned int res; for (;;) { INIT_REQUEST; req = CURRENT; spin_unlock_irq(QUEUE_LOCK(QUEUE)); mtdblk = mtdblks[minor(req->rq_dev)]; res = 0; if (minor(req->rq_dev) >= MAX_MTD_DEVICES) panic("%s : minor out of bound", __FUNCTION__); if (!IS_REQ_CMD(req)) goto end_req; if ((req->sector + req->current_nr_sectors) > (mtdblk->mtd->size >> 9)) goto end_req; // Handle the request switch (rq_data_dir(req)) { int err; case READ: down(&mtdblk->cache_sem); err = do_cached_read (mtdblk, req->sector << 9, req->current_nr_sectors << 9, req->buffer); up(&mtdblk->cache_sem); if (!err) res = 1; break; case WRITE: // Read only device if ( !(mtdblk->mtd->flags & MTD_WRITEABLE) ) break; // Do the write down(&mtdblk->cache_sem); err = do_cached_write (mtdblk, req->sector << 9,req->current_nr_sectors << 9, req->buffer); up(&mtdblk->cache_sem); if (!err) res = 1; break; } end_req: spin_lock_irq(QUEUE_LOCK(QUEUE)); end_request(res); } } int __init init_mtdblock(void) { int i; spin_lock_init(&mtdblks_lock); /* this lock is used just in kernels >= 2.5.x */ spin_lock_init(&mtdblock_lock); #ifdef CONFIG_DEVFS_FS if (devfs_register_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME, &mtd_fops)) { printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",MTD_BLOCK_MAJOR); return -EAGAIN; } devfs_dir_handle = devfs_mk_dir(NULL, DEVICE_NAME, NULL); register_mtd_user(¬ifier); #else if (register_blkdev(MAJOR_NR,DEVICE_NAME,&mtd_fops)) { printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n",MTD_BLOCK_MAJOR); return -EAGAIN; } #endif /* We fill it in at open() time. */ for (i=0; i< MAX_MTD_DEVICES; i++) { mtd_sizes = 0; mtd_blksizes = BLOCK_SIZE; } init_waitqueue_head(&thr_wq); /* Allow the block size to default to BLOCK_SIZE. */ blksize_size[MAJOR_NR] = mtd_blksizes; blk_size[MAJOR_NR] = mtd_sizes; BLK_INIT_QUEUE(BLK_DEFAULT_QUEUE(MAJOR_NR), &mtdblock_request, &mtdblock_lock); kernel_thread (mtdblock_thread, NULL, CLONE_FS|CLONE_FILES|CLONE_SIGHAND); return 0; } static void __exit cleanup_mtdblock(void) { leaving = 1; wake_up(&thr_wq); down(&thread_sem); #ifdef CONFIG_DEVFS_FS unregister_mtd_user(¬ifier); devfs_unregister(devfs_dir_handle); devfs_unregister_blkdev(MTD_BLOCK_MAJOR, DEVICE_NAME); #else unregister_blkdev(MAJOR_NR,DEVICE_NAME); #endif blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR)); blksize_size[MAJOR_NR] = NULL; blk_size[MAJOR_NR] = NULL; } |
[火星人 ] Linux設備驅動編程之複雜設備驅動已經有695次圍觀