?? mmc_core.c
字號:
struct dma_buf_pool_s dma_read_buf_pool[MAX_BUF_POOL_SIZE];static spinlock_t buf_pool_lock = SPIN_LOCK_UNLOCKED;static spinlock_t write_lock = SPIN_LOCK_UNLOCKED;static spinlock_t read_lock = SPIN_LOCK_UNLOCKED;static DECLARE_COMPLETION(sync_completion);static DECLARE_COMPLETION(read_completion);static DECLARE_COMPLETION(write_completion);static unsigned int sync_wait = 0;static unsigned int write_wait = 0;static unsigned int flag_read_request_on = 0;static unsigned int flag_read_thread_wait = 0;static unsigned int mmc_max_size = 0;#define dbgMMC(x...) void init_dma_buf_pool(struct dma_buf_pool_s * dma_buf_pool, struct list_head * head, unsigned int size){ unsigned int i; for (i = 0; i < size; i++) { dma_buf_pool[i].index = i; dma_buf_pool[i].dma_buf_pool_ptr =(unsigned char *) __get_free_pages(GFP_KERNEL, 5); list_add_tail(&dma_buf_pool[i].dma_buf, head); dbgMMC("head %x, num = %d, buf = %x\r\n", head, i, dma_buf_pool[i].dma_buf_pool_ptr); }}void release_dma_buf_pool(struct dma_buf_pool_s * dma_buf_pool, struct list_head * head, unsigned int size){ unsigned int i; dbgMMC("release buf\r\n"); for (i = 0; i < size; i++) { dma_buf_pool[i].index = 0; free_pages((unsigned long)dma_buf_pool[i].dma_buf_pool_ptr, 5); dma_buf_pool[i].dma_buf_pool_ptr = NULL; INIT_LIST_HEAD(head); }}struct dma_buf_pool_s * mas_get_dma_buf(struct list_head * head){ struct dma_buf_pool_s * dma_buf; unsigned long flags; spin_lock_irqsave(&buf_pool_lock, flags); if (!list_empty(head)) { dma_buf = list_entry(head->next, struct dma_buf_pool_s, dma_buf); list_del(&dma_buf->dma_buf); spin_unlock_irqrestore(&buf_pool_lock, flags); return dma_buf; } spin_unlock_irqrestore(&buf_pool_lock, flags); printk("get dam_buf NULL\r\n"); return NULL;}void mas_release_dma_buf(struct list_head * head, struct dma_buf_pool_s * dma_buf){ unsigned long flags; spin_lock_irqsave(&buf_pool_lock, flags); list_add_tail(&dma_buf->dma_buf, head); spin_unlock_irqrestore(&buf_pool_lock, flags);}void mmc_set_max_size(unsigned int size){ mmc_max_size = size;}static void mmc_reset_read_buf_pool(void){ unsigned int i; for (i = 0; i < (read_request_head + MAX_READ_AHEAD_REQUEST - read_request_tail)%MAX_READ_AHEAD_REQUEST; i ++) { mas_release_dma_buf(&dma_read_buf_pool_head, read_request_pool[(read_request_tail + i)%MAX_READ_AHEAD_REQUEST].dma_buf); } read_request_head = 0; read_request_tail = 0;}void new_io_request_done(struct mmc_io_request * req, int result){ return;}static void mmc_read_wait_done(struct mmc_io_request * req){ unsigned int sector, nr_sectors; struct dma_buf_pool_s * dma_buf; spin_lock_irq(&read_lock); if (flag_read_thread_wait == 1) { complete(req->done_data); g_mmc_dev.slot[0].media_driver->io_request_done = old_io_request_done; flag_read_request_on = 0; read_request_head = (read_request_head + 1)%MAX_READ_AHEAD_REQUEST; } else { if ((((read_request_head + 2)%MAX_READ_AHEAD_REQUEST) == read_request_tail) || list_empty(&dma_read_buf_pool_head)) { flag_read_request_on = 0; g_mmc_dev.slot[0].media_driver->io_request_done = old_io_request_done; read_request_head = (read_request_head + 1)%MAX_READ_AHEAD_REQUEST; } else { sector = read_request_pool[read_request_head].sector; nr_sectors = read_request_pool[read_request_head].nr_sectors; dma_buf = mas_get_dma_buf(&dma_read_buf_pool_head); gg_io_read_request.id = 0; gg_io_read_request.cmd = 1; if((sector + nr_sectors + nr_sectors) < mmc_max_size) { gg_io_read_request.sector = sector + nr_sectors; gg_io_read_request.nr_sectors = nr_sectors; } else { dbgMMC("At the bottom, sector %d, nr_sectors %d, max_size %d\r\n", sector, nr_sectors, mmc_max_size); gg_io_read_request.sector = sector; gg_io_read_request.nr_sectors = nr_sectors; } gg_io_read_request.block_len = 512; read_request_head = (read_request_head + 1)%MAX_READ_AHEAD_REQUEST; gg_io_read_request.buffer = dma_buf->dma_buf_pool_ptr; read_request_pool[read_request_head].dma_buf = dma_buf; read_request_pool[read_request_head].sector = sector + nr_sectors; read_request_pool[read_request_head].nr_sectors = nr_sectors; gg_io_read_request.done_data = &read_completion; gg_io_read_request.done = mmc_read_wait_done; flag_read_request_on = 1; mmc_handle_io_request(&gg_io_read_request); } } spin_unlock_irq(&read_lock);}void mmc_block_read_request(int cmd, int sector, int nr_sectors, struct dma_buf_pool_s * * dma_buf){ unsigned int i, cnt; unsigned int flag_data_available; spin_lock_irq(&write_lock); if (write_request_tail != write_request_head) { sync_wait = 1; spin_unlock_irq(&write_lock); wait_for_completion(&sync_completion); spin_lock_irq(&read_lock); sync_wait = 0; if (flag_read_request_on == 1) { flag_read_thread_wait = 1; spin_unlock_irq(&read_lock); wait_for_completion(&read_completion); spin_lock_irq(&read_lock); flag_read_thread_wait = 0; } mmc_reset_read_buf_pool(); spin_unlock_irq(&read_lock); spin_lock_irq(&write_lock); } spin_unlock_irq(&write_lock); spin_lock_irq(&read_lock); flag_data_available = 0; cnt = (read_request_head + MAX_READ_AHEAD_REQUEST - read_request_tail)%MAX_READ_AHEAD_REQUEST; for (i = 0; i < cnt; i ++) { if ((read_request_pool[(read_request_tail + i)%MAX_READ_AHEAD_REQUEST].sector == sector) && (read_request_pool[(read_request_tail + i)%MAX_READ_AHEAD_REQUEST].nr_sectors >= nr_sectors)) { flag_data_available = 1; * dma_buf = read_request_pool[(read_request_tail +i)%MAX_READ_AHEAD_REQUEST].dma_buf; read_request_tail = (read_request_tail + i + 1)%MAX_READ_AHEAD_REQUEST; if(flag_read_request_on == 1) { spin_unlock_irq(&read_lock); return; } else { if (!list_empty(&dma_read_buf_pool_head)) { sector = sector + nr_sectors; goto mmc_mas_submit_request; } else { spin_unlock_irq(&read_lock); return; } } } else { mas_release_dma_buf(&dma_read_buf_pool_head, read_request_pool[(read_request_tail + i)%MAX_READ_AHEAD_REQUEST].dma_buf); } } read_request_tail = read_request_head; if (flag_read_request_on == 1) { flag_read_thread_wait = 1; spin_unlock_irq(&read_lock); wait_for_completion(&read_completion); spin_lock_irq(&read_lock); flag_read_thread_wait = 0; if ((read_request_pool[read_request_tail].sector == sector) && (read_request_pool[read_request_tail].nr_sectors >= nr_sectors)) { *dma_buf = read_request_pool[read_request_tail].dma_buf; read_request_tail = (read_request_tail + 1)%MAX_READ_AHEAD_REQUEST; flag_data_available = 1; sector = sector + nr_sectors; } else { mas_release_dma_buf(&dma_read_buf_pool_head, read_request_pool[read_request_tail].dma_buf); read_request_tail = (read_request_tail + 1)%MAX_READ_AHEAD_REQUEST; } }mmc_mas_submit_request: read_request_pool[read_request_head].dma_buf = mas_get_dma_buf(&dma_read_buf_pool_head); gg_io_read_request.id = 0; gg_io_read_request.cmd = cmd; gg_io_read_request.sector = sector; gg_io_read_request.nr_sectors = nr_sectors; gg_io_read_request.block_len = 512; gg_io_read_request.buffer = read_request_pool[read_request_head].dma_buf->dma_buf_pool_ptr; gg_io_read_request.done_data = &read_completion; gg_io_read_request.done = mmc_read_wait_done; read_request_pool[read_request_head].sector = sector; read_request_pool[read_request_head].nr_sectors = nr_sectors; old_io_request_done = g_mmc_dev.slot[0].media_driver->io_request_done; g_mmc_dev.slot[0].media_driver->io_request_done = new_io_request_done; flag_read_request_on = 1; mmc_handle_io_request(&gg_io_read_request); if (flag_data_available == 0) { flag_read_thread_wait = 1; spin_unlock_irq(&read_lock); wait_for_completion(&read_completion); spin_lock_irq(&read_lock); flag_read_thread_wait = 0; * dma_buf = read_request_pool[read_request_tail].dma_buf; read_request_tail = (read_request_tail + 1)%MAX_READ_AHEAD_REQUEST; flag_data_available = 1; if((sector + nr_sectors + nr_sectors) < mmc_max_size) { sector = sector + nr_sectors; } goto mmc_mas_submit_request; } spin_unlock_irq(&read_lock); return;}static void mmc_write_wait_done(struct mmc_io_request * req){ spin_lock_irq(&write_lock); if (((write_request_head + 1)%MAX_WRITE_PENDING_REQUEST) == write_request_tail) { if(write_wait == 1) complete(&write_completion); } mas_release_dma_buf(&dma_write_buf_pool_head, write_request_pool[write_request_tail]); write_request_tail = (write_request_tail + 1)%MAX_WRITE_PENDING_REQUEST; if (write_request_tail == write_request_head) { g_mmc_dev.slot[0].media_driver->io_request_done = old_io_request_done; if(sync_wait == 1) complete(&sync_completion); } else { mmc_handle_io_request(&gg_io_write_request[write_request_tail]); } spin_unlock_irq(&write_lock);}void mmc_block_write_request(int cmd, int sector, int nr_sectors, struct dma_buf_pool_s * dma_buf){ spin_lock_irq(&write_lock); if (((write_request_head + 1)%MAX_WRITE_PENDING_REQUEST) == write_request_tail) { write_wait = 1; spin_unlock_irq(&write_lock); wait_for_completion(&write_completion); write_wait = 0; spin_lock_irq(&write_lock); } write_request_pool[write_request_head] = dma_buf; gg_io_write_request[write_request_head].id = 0; gg_io_write_request[write_request_head].cmd = cmd; gg_io_write_request[write_request_head].sector = sector; gg_io_write_request[write_request_head].nr_sectors = nr_sectors; gg_io_write_request[write_request_head].block_len = 512; gg_io_write_request[write_request_head].buffer = dma_buf->dma_buf_pool_ptr; gg_io_write_request[write_request_head].done_data = &write_completion; gg_io_write_request[write_request_head].done = mmc_write_wait_done; if (write_request_head == write_request_tail ) { spin_unlock_irq(&write_lock); spin_lock_irq(&read_lock); if (flag_read_request_on == 1) { flag_read_thread_wait = 1; spin_unlock_irq(&read_lock); wait_for_completion(&read_completion); spin_lock_irq(&read_lock); flag_read_thread_wait = 0; } mmc_reset_read_buf_pool(); spin_unlock_irq(&read_lock); spin_lock_irq(&write_lock); old_io_request_done = g_mmc_dev.slot[0].media_driver->io_request_done; g_mmc_dev.slot[0].media_driver->io_request_done = new_io_request_done; mmc_handle_io_request(&gg_io_write_request[write_request_head]); } write_request_head = (write_request_head + 1)%MAX_WRITE_PENDING_REQUEST; spin_unlock_irq(&write_lock);}#endifstatic int mmc_proc_read_device(char *page, char **start, off_t off, int count, int *eof, void *data){ struct mmc_dev *dev = (struct mmc_dev *)data; char *p = page; int len = 0; int i; if (!dev || !dev->sdrive) return 0; for ( i = 0 ; i < dev->num_slots ; i++ ) { struct mmc_slot *slot = &dev->slot[i]; p += sprintf(p, "Slot #%d\n", i); p += sprintf(p, " State %s (%d)\n", card_state_to_string(slot->state), slot->state); if ( slot->state != CARD_STATE_EMPTY ) { p += sprintf(p, " Media %s\n", (slot->media_driver ? slot->media_driver->name : "unknown")); p += sprintf(p, " CID mid=%d\n", slot->cid.mid); p += sprintf(p, " oid=%d\n", slot->cid.oid); p += sprintf(p, " pnm=%s\n", slot->cid.pnm); p += sprintf(p, " prv=%d.%d\n", slot->cid.prv>>4, slot->cid.prv&0xf); p += sprintf(p, " psn=0x%08x\n", slot->cid.psn); p += sprintf(p, " mdt=%d/%d\n", slot->cid.mdt>>4, (slot->cid.mdt&0xf)+1997); p += sprintf(p, " CSD csd_structure=%d\n", slot->csd.csd_structure); p += sprintf(p, " spec_vers=%d\n", slot->csd.spec_vers); p += sprintf(p, " taac=0x%02x\n", slot->csd.taac); p += sprintf(p, " nsac=0x%02x\n", slot->csd.nsac); p += sprintf(p, " tran_speed=0x%02x\n", slot->csd.tran_speed); p += sprintf(p, " ccc=0x%04x\n", slot->csd.ccc); p += sprintf(p, " read_bl_len=%d\n", slot->csd.read_bl_len); p += sprintf(p, " read_bl_partial=%d\n", slot->csd.read_bl_partial); p += sprintf(p, " write_blk_misalign=%d\n", slot->csd.write_blk_misalign); p += sprintf(p, " read_blk_misalign=%d\n", slot->csd.read_blk_misalign); p += sprintf(p, " dsr_imp=%d\n", slot->csd.dsr_imp); p += sprintf(p, " c_size=%d\n", slot->csd.c_size); p += sprintf(p, " vdd_r_curr_min=%d\n", slot->csd.vdd_r_curr_min); p += sprintf(p, " vdd_r_curr_max=%d\n", slot->csd.vdd_r_curr_max); p += sprintf(p, " vdd_w_curr_min=%d\n", slot->csd.vdd_w_curr_min); p += sprintf(p, " vdd_w_curr_max=%d\n", slot->csd.vdd_w_curr_max); p += sprintf(p, " c_size_mult=%d\n", slot->csd.c_size_mult); p += sprintf(p, " wp_grp_size=%d\n", slot->csd.wp_grp_size); p += sprintf(p, " wp_grp_enable=%d\n", slot->csd.wp_grp_enable); p += sprintf(p, " default_ecc=%d\n", slot->csd.default_ecc); p += sprintf(p, " r2w_factor=%d\n", slot->csd.r2w_factor); p += sprintf(p, " write_bl_len=%d\n", slot->csd.write_bl_len); p += sprintf(p, " write_bl_partial=%d\n", slot->csd.write_bl_partial); p += sprintf(p, " file_format_grp=%d\n", slot->csd.file_format_grp); p += sprintf(p, " copy=%d\n", slot->csd.copy); p += sprintf(p, " perm_write_protect=%d\n", slot->csd.perm_write_protect); p += sprintf(p, " tmp_write_protect=%d\n", slot->csd.tmp_write_protect); p += sprintf(p, " file_format=%d\n", slot->csd.file_format); p += sprintf(p, " ecc=%d\n", slot->csd.ecc); switch (slot->csd.csd_structure) { case CSD_STRUCT_VER_1_0: case CSD_STRUCT_VER_1_1: p += sprintf(p, " sector_size=%d\n", slot->csd.erase.v22.sector_size); p += sprintf(p, " erase_grp_size=%d\n", slot->csd.erase.v22.erase_grp_size); break; case CSD_STRUCT_VER_1_2: default: p += sprintf(p, " erase_grp_size=%d\n", slot->csd.erase.v31.erase_grp_size); p += sprintf(p, " erase_grp_mult=%d\n", slot->csd.erase.v31.erase_grp_mult); break; } } } len = (p - page) - off; *start = page + off; return len;}/******************************************************************/void mmc_protocol_single_card( struct mmc_dev *dev, int state_flags );extern struct mmc_media_module media_module;static int __init mmc_init(void) { DEBUG(1, "Init MMC subsystem\n"); mmc_sysctl_header = register_sysctl_table(bus_dir_table, 0 ); tasklet_init(&g_mmc_dev.task,mmc_tasklet_action,(unsigned long)&g_mmc_dev); g_mmc_dev.protocol = mmc_protocol_single_card; proc_mmc_dir = proc_mkdir("mmc", proc_bus); if ( proc_mmc_dir ) create_proc_read_entry("device", 0, proc_mmc_dir, mmc_proc_read_device, &g_mmc_dev); mmc_pm_dev = pm_register(PM_UNKNOWN_DEV, PM_SYS_UNKNOWN, mmc_pm_callback); #ifdef CONFIG_CEE mmc_ldm_register();#endif /* CONFIG_CEE */ media_module.init(); return 0;}static void __exit mmc_exit(void){ DEBUG(1,"\n"); media_module.cleanup(); unregister_sysctl_table(mmc_sysctl_header); tasklet_kill(&g_mmc_dev.task); if ( proc_mmc_dir ) { remove_proc_entry("device", proc_mmc_dir); remove_proc_entry("mmc", proc_bus); } pm_unregister(mmc_pm_dev); #ifdef CONFIG_CEE mmc_ldm_unregister();#endif /* CONFIG_CEE */ }module_init(mmc_init);module_exit(mmc_exit);MODULE_LICENSE("GPL");
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -