📄 bulkmem.c
字号:
This stuff is used by Card Services to initialize the table of region info used for subsequent calls to GetFirstRegion and GetNextRegion. ======================================================================*/static void setup_regions(client_handle_t handle, int attr, memory_handle_t *list){ int i, code, has_jedec, has_geo; u_int offset; cistpl_device_t device; cistpl_jedec_t jedec; cistpl_device_geo_t geo; memory_handle_t r; DEBUG(1, "cs: setup_regions(0x%p, %d, 0x%p)\n", handle, attr, list); code = (attr) ? CISTPL_DEVICE_A : CISTPL_DEVICE; if (read_tuple(handle, code, &device) != CS_SUCCESS) return; code = (attr) ? CISTPL_JEDEC_A : CISTPL_JEDEC_C; has_jedec = (read_tuple(handle, code, &jedec) == CS_SUCCESS); if (has_jedec && (device.ndev != jedec.nid)) {#ifdef PCMCIA_DEBUG printk(KERN_DEBUG "cs: Device info does not match JEDEC info.\n");#endif has_jedec = 0; } code = (attr) ? CISTPL_DEVICE_GEO_A : CISTPL_DEVICE_GEO; has_geo = (read_tuple(handle, code, &geo) == CS_SUCCESS); if (has_geo && (device.ndev != geo.ngeo)) {#ifdef PCMCIA_DEBUG printk(KERN_DEBUG "cs: Device info does not match geometry tuple.\n");#endif has_geo = 0; } offset = 0; for (i = 0; i < device.ndev; i++) { if ((device.dev[i].type != CISTPL_DTYPE_NULL) && (device.dev[i].size != 0)) { r = kmalloc(sizeof(*r), GFP_KERNEL); r->region_magic = REGION_MAGIC; r->state = 0; r->dev_info[0] = '\0'; r->mtd = NULL; r->info.Attributes = (attr) ? REGION_TYPE_AM : 0; r->info.CardOffset = offset; r->info.RegionSize = device.dev[i].size; r->info.AccessSpeed = device.dev[i].speed; if (has_jedec) { r->info.JedecMfr = jedec.id[i].mfr; r->info.JedecInfo = jedec.id[i].info; } else r->info.JedecMfr = r->info.JedecInfo = 0; if (has_geo) { r->info.BlockSize = geo.geo[i].buswidth * geo.geo[i].erase_block * geo.geo[i].interleave; r->info.PartMultiple = r->info.BlockSize * geo.geo[i].partition; } else r->info.BlockSize = r->info.PartMultiple = 1; r->info.next = *list; *list = r; } offset += device.dev[i].size; }} /* setup_regions *//*====================================================================== This is tricky. When get_first_region() is called by Driver Services, we initialize the region info table in the socket structure. When it is called by an MTD, we can just scan the table for matching entries. ======================================================================*/static int match_region(client_handle_t handle, memory_handle_t list, region_info_t *match){ while (list != NULL) { if (!(handle->Attributes & INFO_MTD_CLIENT) || (strcmp(handle->dev_info, list->dev_info) == 0)) { *match = list->info; return CS_SUCCESS; } list = list->info.next; } return CS_NO_MORE_ITEMS;} /* match_region */int pcmcia_get_first_region(client_handle_t handle, region_info_t *rgn){ socket_info_t *s = SOCKET(handle); if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; if ((handle->Attributes & INFO_MASTER_CLIENT) && (!(s->state & SOCKET_REGION_INFO))) { setup_regions(handle, 0, &s->c_region); setup_regions(handle, 1, &s->a_region); s->state |= SOCKET_REGION_INFO; } if (rgn->Attributes & REGION_TYPE_AM) return match_region(handle, s->a_region, rgn); else return match_region(handle, s->c_region, rgn);} /* get_first_region */int pcmcia_get_next_region(client_handle_t handle, region_info_t *rgn){ if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; return match_region(handle, rgn->next, rgn);} /* get_next_region *//*====================================================================== Connect an MTD with a memory region. ======================================================================*/int pcmcia_register_mtd(client_handle_t handle, mtd_reg_t *reg){ memory_handle_t list; socket_info_t *s; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); if (reg->Attributes & REGION_TYPE_AM) list = s->a_region; else list = s->c_region; DEBUG(1, "cs: register_mtd(0x%p, '%s', 0x%x)\n", handle, handle->dev_info, reg->Offset); while (list) { if (list->info.CardOffset == reg->Offset) break; list = list->info.next; } if (list && (list->mtd == NULL) && (strcmp(handle->dev_info, list->dev_info) == 0)) { list->info.Attributes = reg->Attributes; list->MediaID = reg->MediaID; list->mtd = handle; handle->mtd_count++; return CS_SUCCESS; } else return CS_BAD_OFFSET;} /* register_mtd *//*====================================================================== Erase queue management functions ======================================================================*/int pcmcia_register_erase_queue(client_handle_t *handle, eraseq_hdr_t *header, eraseq_handle_t *e){ eraseq_t *queue; if ((handle == NULL) || CHECK_HANDLE(*handle)) return CS_BAD_HANDLE; queue = kmalloc(sizeof(*queue), GFP_KERNEL); if (!queue) return CS_OUT_OF_RESOURCE; queue->eraseq_magic = ERASEQ_MAGIC; queue->handle = *handle; queue->count = header->QueueEntryCnt; queue->entry = header->QueueEntryArray; *e = queue; return CS_SUCCESS;} /* register_erase_queue */int pcmcia_deregister_erase_queue(eraseq_handle_t eraseq){ int i; if (CHECK_ERASEQ(eraseq)) return CS_BAD_HANDLE; for (i = 0; i < eraseq->count; i++) if (ERASE_IN_PROGRESS(eraseq->entry[i].State)) break; if (i < eraseq->count) return CS_BUSY; eraseq->eraseq_magic = 0; kfree(eraseq); return CS_SUCCESS;} /* deregister_erase_queue */int pcmcia_check_erase_queue(eraseq_handle_t eraseq){ int i; if (CHECK_ERASEQ(eraseq)) return CS_BAD_HANDLE; for (i = 0; i < eraseq->count; i++) if (eraseq->entry[i].State == ERASE_QUEUED) setup_erase_request(eraseq->handle, &eraseq->entry[i]); return CS_SUCCESS;} /* check_erase_queue *//*====================================================================== Look up the memory region matching the request, and return a memory handle. ======================================================================*/int pcmcia_open_memory(client_handle_t *handle, open_mem_t *open, memory_handle_t *mh){ socket_info_t *s; memory_handle_t region; if ((handle == NULL) || CHECK_HANDLE(*handle)) return CS_BAD_HANDLE; s = SOCKET(*handle); if (open->Attributes & MEMORY_TYPE_AM) region = s->a_region; else region = s->c_region; while (region) { if (region->info.CardOffset == open->Offset) break; region = region->info.next; } if (region && region->mtd) { *mh = region; DEBUG(1, "cs: open_memory(0x%p, 0x%x) = 0x%p\n", handle, open->Offset, region); return CS_SUCCESS; } else return CS_BAD_OFFSET;} /* open_memory *//*====================================================================== Close a memory handle from an earlier call to OpenMemory. For the moment, I don't think this needs to do anything. ======================================================================*/int pcmcia_close_memory(memory_handle_t handle){ DEBUG(1, "cs: close_memory(0x%p)\n", handle); if (CHECK_REGION(handle)) return CS_BAD_HANDLE; return CS_SUCCESS;} /* close_memory *//*====================================================================== Read from a memory device, using a handle previously returned by a call to OpenMemory. ======================================================================*/int pcmcia_read_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf){ mtd_request_t mtd; if (CHECK_REGION(handle)) return CS_BAD_HANDLE; if (req->Offset >= handle->info.RegionSize) return CS_BAD_OFFSET; if (req->Offset+req->Count > handle->info.RegionSize) return CS_BAD_SIZE; mtd.SrcCardOffset = req->Offset + handle->info.CardOffset; mtd.TransferLength = req->Count; mtd.MediaID = handle->MediaID; mtd.Function = MTD_REQ_READ; if (req->Attributes & MEM_OP_BUFFER_KERNEL) mtd.Function |= MTD_REQ_KERNEL; return do_mtd_request(handle, &mtd, buf);} /* read_memory *//*====================================================================== Write to a memory device, using a handle previously returned by a call to OpenMemory. ======================================================================*/int pcmcia_write_memory(memory_handle_t handle, mem_op_t *req, caddr_t buf){ mtd_request_t mtd; if (CHECK_REGION(handle)) return CS_BAD_HANDLE; if (req->Offset >= handle->info.RegionSize) return CS_BAD_OFFSET; if (req->Offset+req->Count > handle->info.RegionSize) return CS_BAD_SIZE; mtd.DestCardOffset = req->Offset + handle->info.CardOffset; mtd.TransferLength = req->Count; mtd.MediaID = handle->MediaID; mtd.Function = MTD_REQ_WRITE; if (req->Attributes & MEM_OP_BUFFER_KERNEL) mtd.Function |= MTD_REQ_KERNEL; return do_mtd_request(handle, &mtd, buf);} /* write_memory *//*====================================================================== This isn't needed for anything I could think of. ======================================================================*/int pcmcia_copy_memory(memory_handle_t handle, copy_op_t *req){ if (CHECK_REGION(handle)) return CS_BAD_HANDLE; return CS_UNSUPPORTED_FUNCTION;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -