📄 cs.c
字号:
{ client_t *client; socket_info_t *s; if (CHECK_SOCKET(req->Socket)) return CS_BAD_SOCKET; s = SOCKET(req); client = (client_t *)kmalloc(sizeof(client_t), GFP_KERNEL); if (!client) return CS_OUT_OF_RESOURCE; memset(client, '\0', sizeof(client_t)); client->client_magic = CLIENT_MAGIC; strncpy(client->dev_info, (char *)req->dev_info, DEV_NAME_LEN); client->Socket = req->Socket; client->Function = req->Function; client->state = CLIENT_UNBOUND; client->erase_busy.next = &client->erase_busy; client->erase_busy.prev = &client->erase_busy; init_waitqueue_head(&client->mtd_req); client->next = s->clients; s->clients = client; DEBUG(1, "cs: bind_device(): client 0x%p, sock %d, dev %s\n", client, client->Socket, client->dev_info); return CS_SUCCESS;} /* bind_device *//*====================================================================== Bind_mtd() associates a device driver with a particular memory region. It is normally called by Driver Services after it has identified a memory device type. An instance of the corresponding driver will then be able to register to control this region. ======================================================================*/int pcmcia_bind_mtd(mtd_bind_t *req){ socket_info_t *s; memory_handle_t region; if (CHECK_SOCKET(req->Socket)) return CS_BAD_SOCKET; s = SOCKET(req); if (req->Attributes & REGION_TYPE_AM) region = s->a_region; else region = s->c_region; while (region) { if (region->info.CardOffset == req->CardOffset) break; region = region->info.next; } if (!region || (region->mtd != NULL)) return CS_BAD_OFFSET; strncpy(region->dev_info, (char *)req->dev_info, DEV_NAME_LEN); DEBUG(1, "cs: bind_mtd(): attr 0x%x, offset 0x%x, dev %s\n", req->Attributes, req->CardOffset, (char *)req->dev_info); return CS_SUCCESS;} /* bind_mtd *//*====================================================================*/int pcmcia_deregister_client(client_handle_t handle){ client_t **client; socket_info_t *s; memory_handle_t region; u_long flags; int i, sn; DEBUG(1, "cs: deregister_client(%p)\n", handle); if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; if (handle->state & (CLIENT_IRQ_REQ|CLIENT_IO_REQ|CLIENT_CONFIG_LOCKED)) return CS_IN_USE; for (i = 0; i < MAX_WIN; i++) if (handle->state & CLIENT_WIN_REQ(i)) return CS_IN_USE; /* Disconnect all MTD links */ s = SOCKET(handle); if (handle->mtd_count) { for (region = s->a_region; region; region = region->info.next) if (region->mtd == handle) region->mtd = NULL; for (region = s->c_region; region; region = region->info.next) if (region->mtd == handle) region->mtd = NULL; } sn = handle->Socket; s = socket_table[sn]; if ((handle->state & CLIENT_STALE) || (handle->Attributes & INFO_MASTER_CLIENT)) { spin_lock_irqsave(&s->lock, flags); client = &s->clients; while ((*client) && ((*client) != handle)) client = &(*client)->next; if (*client == NULL) { spin_unlock_irqrestore(&s->lock, flags); return CS_BAD_HANDLE; } *client = handle->next; handle->client_magic = 0; kfree(handle); spin_unlock_irqrestore(&s->lock, flags); } else { handle->state = CLIENT_UNBOUND; handle->mtd_count = 0; handle->event_handler = NULL; } if (--s->real_clients == 0) register_callback(s, NULL, NULL); return CS_SUCCESS;} /* deregister_client *//*====================================================================*/int pcmcia_get_configuration_info(client_handle_t handle, config_info_t *config){ socket_info_t *s; config_t *c; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (handle->Function == BIND_FN_ALL) { if (config->Function && (config->Function >= s->functions)) return CS_BAD_ARGS; } else config->Function = handle->Function; #ifdef CONFIG_CARDBUS if (s->state & SOCKET_CARDBUS) { u_char fn = config->Function; memset(config, 0, sizeof(config_info_t)); config->Function = fn; config->Vcc = s->socket.Vcc; config->Vpp1 = config->Vpp2 = s->socket.Vpp; config->Option = s->cap.cb_dev->subordinate->number; if (s->cb_config) { config->Attributes = CONF_VALID_CLIENT; config->IntType = INT_CARDBUS; config->AssignedIRQ = s->irq.AssignedIRQ; if (config->AssignedIRQ) config->Attributes |= CONF_ENABLE_IRQ; config->BasePort1 = s->io[0].BasePort; config->NumPorts1 = s->io[0].NumPorts; } return CS_SUCCESS; }#endif c = (s->config != NULL) ? &s->config[config->Function] : NULL; if ((c == NULL) || !(c->state & CONFIG_LOCKED)) { config->Attributes = 0; config->Vcc = s->socket.Vcc; config->Vpp1 = config->Vpp2 = s->socket.Vpp; return CS_SUCCESS; } /* !!! This is a hack !!! */ memcpy(&config->Attributes, &c->Attributes, sizeof(config_t)); config->Attributes |= CONF_VALID_CLIENT; config->CardValues = c->CardValues; config->IRQAttributes = c->irq.Attributes; config->AssignedIRQ = s->irq.AssignedIRQ; config->BasePort1 = c->io.BasePort1; config->NumPorts1 = c->io.NumPorts1; config->Attributes1 = c->io.Attributes1; config->BasePort2 = c->io.BasePort2; config->NumPorts2 = c->io.NumPorts2; config->Attributes2 = c->io.Attributes2; config->IOAddrLines = c->io.IOAddrLines; return CS_SUCCESS;} /* get_configuration_info *//*====================================================================== Return information about this version of Card Services. ======================================================================*/int pcmcia_get_card_services_info(servinfo_t *info){ info->Signature[0] = 'C'; info->Signature[1] = 'S'; info->Count = sockets; info->Revision = CS_RELEASE_CODE; info->CSLevel = 0x0210; info->VendorString = (char *)release; return CS_SUCCESS;} /* get_card_services_info *//*====================================================================== Note that get_first_client() *does* recognize the Socket field in the request structure. ======================================================================*/int pcmcia_get_first_client(client_handle_t *handle, client_req_t *req){ socket_t s; if (req->Attributes & CLIENT_THIS_SOCKET) s = req->Socket; else s = 0; if (CHECK_SOCKET(req->Socket)) return CS_BAD_SOCKET; if (socket_table[s]->clients == NULL) return CS_NO_MORE_ITEMS; *handle = socket_table[s]->clients; return CS_SUCCESS;} /* get_first_client *//*====================================================================*/int pcmcia_get_next_client(client_handle_t *handle, client_req_t *req){ socket_info_t *s; if ((handle == NULL) || CHECK_HANDLE(*handle)) return CS_BAD_HANDLE; if ((*handle)->next == NULL) { if (req->Attributes & CLIENT_THIS_SOCKET) return CS_NO_MORE_ITEMS; s = SOCKET(*handle); if (s->clients == NULL) return CS_NO_MORE_ITEMS; *handle = s->clients; } else *handle = (*handle)->next; return CS_SUCCESS;} /* get_next_client *//*====================================================================*/int pcmcia_get_window(window_handle_t *handle, int idx, win_req_t *req){ socket_info_t *s; window_t *win; int w; if (idx == 0) s = SOCKET((client_handle_t)*handle); else s = (*handle)->sock; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; for (w = idx; w < MAX_WIN; w++) if (s->state & SOCKET_WIN_REQ(w)) break; if (w == MAX_WIN) return CS_NO_MORE_ITEMS; win = &s->win[w]; req->Base = win->ctl.sys_start; req->Size = win->ctl.sys_stop - win->ctl.sys_start + 1; req->AccessSpeed = win->ctl.speed; req->Attributes = 0; if (win->ctl.flags & MAP_ATTRIB) req->Attributes |= WIN_MEMORY_TYPE_AM; if (win->ctl.flags & MAP_ACTIVE) req->Attributes |= WIN_ENABLE; if (win->ctl.flags & MAP_16BIT) req->Attributes |= WIN_DATA_WIDTH_16; if (win->ctl.flags & MAP_USE_WAIT) req->Attributes |= WIN_USE_WAIT; *handle = win; return CS_SUCCESS;} /* get_window */int pcmcia_get_first_window(window_handle_t *win, win_req_t *req){ if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC)) return CS_BAD_HANDLE; return pcmcia_get_window(win, 0, req);}int pcmcia_get_next_window(window_handle_t *win, win_req_t *req){ if ((win == NULL) || ((*win)->magic != WINDOW_MAGIC)) return CS_BAD_HANDLE; return pcmcia_get_window(win, (*win)->index+1, req);}/*===================================================================== Return the PCI device associated with a card..======================================================================*/#ifdef CONFIG_CARDBUSstruct pci_bus *pcmcia_lookup_bus(client_handle_t handle){ socket_info_t *s; if (CHECK_HANDLE(handle)) return NULL; s = SOCKET(handle); if (!(s->state & SOCKET_CARDBUS)) return NULL; return s->cap.cb_dev->subordinate;}EXPORT_SYMBOL(pcmcia_lookup_bus);#endif/*====================================================================== Get the current socket state bits. We don't support the latched SocketState yet: I haven't seen any point for it. ======================================================================*/int pcmcia_get_status(client_handle_t handle, cs_status_t *status){ socket_info_t *s; config_t *c; int val; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); get_socket_status(s, &val); status->CardState = status->SocketState = 0; status->CardState |= (val & SS_DETECT) ? CS_EVENT_CARD_DETECT : 0; status->CardState |= (val & SS_CARDBUS) ? CS_EVENT_CB_DETECT : 0; status->CardState |= (val & SS_3VCARD) ? CS_EVENT_3VCARD : 0; status->CardState |= (val & SS_XVCARD) ? CS_EVENT_XVCARD : 0; if (s->state & SOCKET_SUSPEND) status->CardState |= CS_EVENT_PM_SUSPEND; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (s->state & SOCKET_SETUP_PENDING) status->CardState |= CS_EVENT_CARD_INSERTION; /* Get info from the PRR, if necessary */ if (handle->Function == BIND_FN_ALL) { if (status->Function && (status->Function >= s->functions)) return CS_BAD_ARGS; c = (s->config != NULL) ? &s->config[status->Function] : NULL; } else c = CONFIG(handle); if ((c != NULL) && (c->state & CONFIG_LOCKED) && (c->IntType & INT_MEMORY_AND_IO)) { u_char reg; if (c->Present & PRESENT_PIN_REPLACE) { read_cis_mem(s, 1, (c->ConfigBase+CISREG_PRR)>>1, 1, ®); status->CardState |= (reg & PRR_WP_STATUS) ? CS_EVENT_WRITE_PROTECT : 0; status->CardState |= (reg & PRR_READY_STATUS) ? CS_EVENT_READY_CHANGE : 0; status->CardState |= (reg & PRR_BVD2_STATUS) ? CS_EVENT_BATTERY_LOW : 0; status->CardState |= (reg & PRR_BVD1_STATUS) ? CS_EVENT_BATTERY_DEAD : 0; } else { /* No PRR? Then assume we're always ready */ status->CardState |= CS_EVENT_READY_CHANGE; } if (c->Present & PRESENT_EXT_STATUS) { read_cis_mem(s, 1, (c->ConfigBase+CISREG_ESR)>>1, 1, ®); status->CardState |= (reg & ESR_REQ_ATTN) ? CS_EVENT_REQUEST_ATTENTION : 0; } return CS_SUCCESS; } status->CardState |= (val & SS_WRPROT) ? CS_EVENT_WRITE_PROTECT : 0; status->CardState |= (val & SS_BATDEAD) ? CS_EVENT_BATTERY_DEAD : 0; status->CardState |= (val & SS_BATWARN) ? CS_EVENT_BATTERY_LOW : 0; status->CardState |= (val & SS_READY) ? CS_EVENT_READY_CHANGE : 0; return CS_SUCCESS;} /* get_status *//*====================================================================== Change the card address of an already open memory window. ======================================================================*/int pcmcia_get_mem_page(window_handle_t win, memreq_t *req){ if ((win == NULL) || (win->magic != WINDOW_MAGIC)) return CS_BAD_HANDLE; req->Page = 0; req->CardOffset = win->ctl.card_start; return CS_SUCCESS;} /* get_mem_page */int pcmcia_map_mem_page(window_handle_t win, memreq_t *req){ socket_info_t *s; if ((win == NULL) || (win->magic != WINDOW_MAGIC)) return CS_BAD_HANDLE; if (req->Page != 0) return CS_BAD_PAGE; s = win->sock; win->ctl.card_start = req->CardOffset; if (set_mem_map(s, &win->ctl) != 0) return CS_BAD_OFFSET; return CS_SUCCESS;} /* map_mem_page *//*====================================================================== Modify a locked socket configuration ======================================================================*/int pcmcia_modify_configuration(client_handle_t handle, modconf_t *mod){ socket_info_t *s; config_t *c; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); c = CONFIG(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (!(c->state & CONFIG_LOCKED)) return CS_CONFIGURATION_LOCKED; if (mod->Attributes & CONF_IRQ_CHANGE_VALID) { if (mod->Attributes & CONF_ENABLE_IRQ) { c->Attributes |= CONF_ENABLE_IRQ; s->socket.io_irq = s->irq.AssignedIRQ; } else { c->Attributes &= ~CONF_ENABLE_IRQ; s->socket.io_irq = 0; } set_socket(s, &s->socket); } if (mod->Attributes & CONF_VCC_CHANGE_VALID) return CS_BAD_VCC;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -