📄 umem.c
字号:
return -EINVAL;}/*------------------------------------------------------------------------------------- mm_check_change----------------------------------------------------------------------------------- Future support for removable devices*/static int mm_check_change(struct gendisk *disk){/* struct cardinfo *dev = disk->private_data; */ return 0;}/*------------------------------------------------------------------------------------- mm_fops-----------------------------------------------------------------------------------*/static struct block_device_operations mm_fops = { .owner = THIS_MODULE, .ioctl = mm_ioctl, .revalidate_disk= mm_revalidate, .media_changed = mm_check_change,};/*------------------------------------------------------------------------------------- mm_pci_probe-----------------------------------------------------------------------------------*/static int __devinit mm_pci_probe(struct pci_dev *dev, const struct pci_device_id *id){ int ret = -ENODEV; struct cardinfo *card = &cards[num_cards]; unsigned char mem_present; unsigned char batt_status; unsigned int saved_bar, data; int magic_number; if (pci_enable_device(dev) < 0) return -ENODEV; pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xF8); pci_set_master(dev); card->dev = dev; card->card_number = num_cards; card->csr_base = pci_resource_start(dev, 0); card->csr_len = pci_resource_len(dev, 0);#ifdef CONFIG_MM_MAP_MEMORY card->mem_base = pci_resource_start(dev, 1); card->mem_len = pci_resource_len(dev, 1);#endif printk(KERN_INFO "Micro Memory(tm) controller #%d found at %02x:%02x (PCI Mem Module (Battery Backup))\n", card->card_number, dev->bus->number, dev->devfn); if (pci_set_dma_mask(dev, 0xffffffffffffffffLL) && !pci_set_dma_mask(dev, 0xffffffffLL)) { printk(KERN_WARNING "MM%d: NO suitable DMA found\n",num_cards); return -ENOMEM; } if (!request_mem_region(card->csr_base, card->csr_len, "Micro Memory")) { printk(KERN_ERR "MM%d: Unable to request memory region\n", card->card_number); ret = -ENOMEM; goto failed_req_csr; } card->csr_remap = ioremap_nocache(card->csr_base, card->csr_len); if (!card->csr_remap) { printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number); ret = -ENOMEM; goto failed_remap_csr; } printk(KERN_INFO "MM%d: CSR 0x%08lx -> 0x%p (0x%lx)\n", card->card_number, card->csr_base, card->csr_remap, card->csr_len);#ifdef CONFIG_MM_MAP_MEMORY if (!request_mem_region(card->mem_base, card->mem_len, "Micro Memory")) { printk(KERN_ERR "MM%d: Unable to request memory region\n", card->card_number); ret = -ENOMEM; goto failed_req_mem; } if (!(card->mem_remap = ioremap(card->mem_base, cards->mem_len))) { printk(KERN_ERR "MM%d: Unable to remap memory region\n", card->card_number); ret = -ENOMEM; goto failed_remap_mem; } printk(KERN_INFO "MM%d: MEM 0x%8lx -> 0x%8lx (0x%lx)\n", card->card_number, card->mem_base, card->mem_remap, card->mem_len);#else printk(KERN_INFO "MM%d: MEM area not remapped (CONFIG_MM_MAP_MEMORY not set)\n", card->card_number);#endif switch(card->dev->device) { case 0x5415: card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG; magic_number = 0x59; break; case 0x5425: card->flags |= UM_FLAG_NO_BYTE_STATUS; magic_number = 0x5C; break; case 0x6155: card->flags |= UM_FLAG_NO_BYTE_STATUS | UM_FLAG_NO_BATTREG | UM_FLAG_NO_BATT; magic_number = 0x99; break; default: magic_number = 0x100; break; } if (readb(card->csr_remap + MEMCTRLSTATUS_MAGIC) != magic_number) { printk(KERN_ERR "MM%d: Magic number invalid\n", card->card_number); ret = -ENOMEM; goto failed_magic; } card->mm_pages[0].desc = pci_alloc_consistent(card->dev, PAGE_SIZE*2, &card->mm_pages[0].page_dma); card->mm_pages[1].desc = pci_alloc_consistent(card->dev, PAGE_SIZE*2, &card->mm_pages[1].page_dma); if (card->mm_pages[0].desc == NULL || card->mm_pages[1].desc == NULL) { printk(KERN_ERR "MM%d: alloc failed\n", card->card_number); goto failed_alloc; } reset_page(&card->mm_pages[0]); reset_page(&card->mm_pages[1]); card->Ready = 0; /* page 0 is ready */ card->Active = -1; /* no page is active */ card->bio = NULL; card->biotail = &card->bio; card->queue = blk_alloc_queue(GFP_KERNEL); if (!card->queue) goto failed_alloc; blk_queue_make_request(card->queue, mm_make_request); card->queue->queuedata = card; card->queue->unplug_fn = mm_unplug_device; tasklet_init(&card->tasklet, process_page, (unsigned long)card); card->check_batteries = 0; mem_present = readb(card->csr_remap + MEMCTRLSTATUS_MEMORY); switch (mem_present) { case MEM_128_MB: card->mm_size = 1024 * 128; break; case MEM_256_MB: card->mm_size = 1024 * 256; break; case MEM_512_MB: card->mm_size = 1024 * 512; break; case MEM_1_GB: card->mm_size = 1024 * 1024; break; case MEM_2_GB: card->mm_size = 1024 * 2048; break; default: card->mm_size = 0; break; } /* Clear the LED's we control */ set_led(card, LED_REMOVE, LED_OFF); set_led(card, LED_FAULT, LED_OFF); batt_status = readb(card->csr_remap + MEMCTRLSTATUS_BATTERY); card->battery[0].good = !(batt_status & BATTERY_1_FAILURE); card->battery[1].good = !(batt_status & BATTERY_2_FAILURE); card->battery[0].last_change = card->battery[1].last_change = jiffies; if (card->flags & UM_FLAG_NO_BATT) printk(KERN_INFO "MM%d: Size %d KB\n", card->card_number, card->mm_size); else { printk(KERN_INFO "MM%d: Size %d KB, Battery 1 %s (%s), Battery 2 %s (%s)\n", card->card_number, card->mm_size, (batt_status & BATTERY_1_DISABLED ? "Disabled" : "Enabled"), card->battery[0].good ? "OK" : "FAILURE", (batt_status & BATTERY_2_DISABLED ? "Disabled" : "Enabled"), card->battery[1].good ? "OK" : "FAILURE"); set_fault_to_battery_status(card); } pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, &saved_bar); data = 0xffffffff; pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, data); pci_read_config_dword(dev, PCI_BASE_ADDRESS_1, &data); pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, saved_bar); data &= 0xfffffff0; data = ~data; data += 1; card->win_size = data; if (request_irq(dev->irq, mm_interrupt, SA_SHIRQ, "pci-umem", card)) { printk(KERN_ERR "MM%d: Unable to allocate IRQ\n", card->card_number); ret = -ENODEV; goto failed_req_irq; } card->irq = dev->irq; printk(KERN_INFO "MM%d: Window size %d bytes, IRQ %d\n", card->card_number, card->win_size, card->irq); spin_lock_init(&card->lock); pci_set_drvdata(dev, card); if (pci_write_cmd != 0x0F) /* If not Memory Write & Invalidate */ pci_write_cmd = 0x07; /* then Memory Write command */ if (pci_write_cmd & 0x08) { /* use Memory Write and Invalidate */ unsigned short cfg_command; pci_read_config_word(dev, PCI_COMMAND, &cfg_command); cfg_command |= 0x10; /* Memory Write & Invalidate Enable */ pci_write_config_word(dev, PCI_COMMAND, cfg_command); } pci_cmds = (pci_read_cmd << 28) | (pci_write_cmd << 24); num_cards++; if (!get_userbit(card, MEMORY_INITIALIZED)) { printk(KERN_INFO "MM%d: memory NOT initialized. Consider over-writing whole device.\n", card->card_number); card->init_size = 0; } else { printk(KERN_INFO "MM%d: memory already initialized\n", card->card_number); card->init_size = card->mm_size; } /* Enable ECC */ writeb(EDC_STORE_CORRECT, card->csr_remap + MEMCTRLCMD_ERRCTRL); return 0; failed_req_irq: failed_alloc: if (card->mm_pages[0].desc) pci_free_consistent(card->dev, PAGE_SIZE*2, card->mm_pages[0].desc, card->mm_pages[0].page_dma); if (card->mm_pages[1].desc) pci_free_consistent(card->dev, PAGE_SIZE*2, card->mm_pages[1].desc, card->mm_pages[1].page_dma); failed_magic:#ifdef CONFIG_MM_MAP_MEMORY iounmap(card->mem_remap); failed_remap_mem: release_mem_region(card->mem_base, card->mem_len); failed_req_mem:#endif iounmap(card->csr_remap); failed_remap_csr: release_mem_region(card->csr_base, card->csr_len); failed_req_csr: return ret;}/*------------------------------------------------------------------------------------- mm_pci_remove-----------------------------------------------------------------------------------*/static void mm_pci_remove(struct pci_dev *dev){ struct cardinfo *card = pci_get_drvdata(dev); tasklet_kill(&card->tasklet); iounmap(card->csr_remap); release_mem_region(card->csr_base, card->csr_len);#ifdef CONFIG_MM_MAP_MEMORY iounmap(card->mem_remap); release_mem_region(card->mem_base, card->mem_len);#endif free_irq(card->irq, card); if (card->mm_pages[0].desc) pci_free_consistent(card->dev, PAGE_SIZE*2, card->mm_pages[0].desc, card->mm_pages[0].page_dma); if (card->mm_pages[1].desc) pci_free_consistent(card->dev, PAGE_SIZE*2, card->mm_pages[1].desc, card->mm_pages[1].page_dma); blk_put_queue(card->queue);}static const struct pci_device_id mm_pci_ids[] = { { .vendor = PCI_VENDOR_ID_MICRO_MEMORY, .device = PCI_DEVICE_ID_MICRO_MEMORY_5415CN, }, { .vendor = PCI_VENDOR_ID_MICRO_MEMORY, .device = PCI_DEVICE_ID_MICRO_MEMORY_5425CN, }, { .vendor = PCI_VENDOR_ID_MICRO_MEMORY, .device = PCI_DEVICE_ID_MICRO_MEMORY_6155, }, { .vendor = 0x8086, .device = 0xB555, .subvendor= 0x1332, .subdevice= 0x5460, .class = 0x050000, .class_mask= 0, }, { /* end: all zeroes */ }};MODULE_DEVICE_TABLE(pci, mm_pci_ids);static struct pci_driver mm_pci_driver = { .name = "umem", .id_table = mm_pci_ids, .probe = mm_pci_probe, .remove = mm_pci_remove,};/*------------------------------------------------------------------------------------- mm_init-----------------------------------------------------------------------------------*/static int __init mm_init(void){ int retval, i; int err; printk(KERN_INFO DRIVER_VERSION " : " DRIVER_DESC "\n"); retval = pci_module_init(&mm_pci_driver); if (retval) return -ENOMEM; err = major_nr = register_blkdev(0, "umem"); if (err < 0) return -EIO; for (i = 0; i < num_cards; i++) { mm_gendisk[i] = alloc_disk(1 << MM_SHIFT); if (!mm_gendisk[i]) goto out; } for (i = 0; i < num_cards; i++) { struct gendisk *disk = mm_gendisk[i]; sprintf(disk->disk_name, "umem%c", 'a'+i); sprintf(disk->devfs_name, "umem/card%d", i); spin_lock_init(&cards[i].lock); disk->major = major_nr; disk->first_minor = i << MM_SHIFT; disk->fops = &mm_fops; disk->private_data = &cards[i]; disk->queue = cards[i].queue; set_capacity(disk, cards[i].mm_size << 1); add_disk(disk); } init_battery_timer(); printk("MM: desc_per_page = %ld\n", DESC_PER_PAGE);/* printk("mm_init: Done. 10-19-01 9:00\n"); */ return 0;out: unregister_blkdev(major_nr, "umem"); while (i--) put_disk(mm_gendisk[i]); return -ENOMEM;}/*------------------------------------------------------------------------------------- mm_cleanup-----------------------------------------------------------------------------------*/static void __exit mm_cleanup(void){ int i; del_battery_timer(); for (i=0; i < num_cards ; i++) { del_gendisk(mm_gendisk[i]); put_disk(mm_gendisk[i]); } pci_unregister_driver(&mm_pci_driver); unregister_blkdev(major_nr, "umem");}module_init(mm_init);module_exit(mm_cleanup);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -