cs.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,183 行 · 第 1/4 页
C
2,183 行
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.res->start; req->Size = win->ctl.res->end - win->ctl.res->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){ struct pcmcia_socket *s; if (CHECK_HANDLE(handle)) return NULL; s = SOCKET(handle); if (!(s->state & SOCKET_CARDBUS)) return NULL; return s->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){ struct pcmcia_socket *s; config_t *c; int val; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); s->ops->get_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; /* 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 | INT_ZOOMED_VIDEO))) { 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){ struct pcmcia_socket *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 (s->ops->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){ struct pcmcia_socket *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; } s->ops->set_socket(s, &s->socket); } if (mod->Attributes & CONF_VCC_CHANGE_VALID) return CS_BAD_VCC; /* We only allow changing Vpp1 and Vpp2 to the same value */ if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) && (mod->Attributes & CONF_VPP2_CHANGE_VALID)) { if (mod->Vpp1 != mod->Vpp2) return CS_BAD_VPP; c->Vpp1 = c->Vpp2 = s->socket.Vpp = mod->Vpp1; if (s->ops->set_socket(s, &s->socket)) return CS_BAD_VPP; } else if ((mod->Attributes & CONF_VPP1_CHANGE_VALID) || (mod->Attributes & CONF_VPP2_CHANGE_VALID)) return CS_BAD_VPP; return CS_SUCCESS;} /* modify_configuration *//*====================================================================== Modify the attributes of a window returned by RequestWindow.======================================================================*/int pcmcia_modify_window(window_handle_t win, modwin_t *req){ if ((win == NULL) || (win->magic != WINDOW_MAGIC)) return CS_BAD_HANDLE; win->ctl.flags &= ~(MAP_ATTRIB|MAP_ACTIVE); if (req->Attributes & WIN_MEMORY_TYPE) win->ctl.flags |= MAP_ATTRIB; if (req->Attributes & WIN_ENABLE) win->ctl.flags |= MAP_ACTIVE; if (req->Attributes & WIN_DATA_WIDTH_16) win->ctl.flags |= MAP_16BIT; if (req->Attributes & WIN_USE_WAIT) win->ctl.flags |= MAP_USE_WAIT; win->ctl.speed = req->AccessSpeed; win->sock->ops->set_mem_map(win->sock, &win->ctl); return CS_SUCCESS;} /* modify_window *//*====================================================================== Register_client() uses the dev_info_t handle to match the caller with a socket. The driver must have already been bound to a socket with bind_device() -- in fact, bind_device() allocates the client structure that will be used. ======================================================================*/int pcmcia_register_client(client_handle_t *handle, client_reg_t *req){ client_t *client = NULL; struct pcmcia_socket *s; /* Look for unbound client with matching dev_info */ down_read(&pcmcia_socket_list_rwsem); list_for_each_entry(s, &pcmcia_socket_list, socket_list) { client = s->clients; while (client != NULL) { if ((strcmp(client->dev_info, (char *)req->dev_info) == 0) && (client->state & CLIENT_UNBOUND)) break; client = client->next; } if (client != NULL) break; } up_read(&pcmcia_socket_list_rwsem); if (client == NULL) return CS_OUT_OF_RESOURCE; /* * Prevent this racing with a card insertion. */ down(&s->skt_sem); *handle = client; client->state &= ~CLIENT_UNBOUND; client->Socket = s; client->Attributes = req->Attributes; client->EventMask = req->EventMask; client->event_handler = req->event_handler; client->event_callback_args = req->event_callback_args; client->event_callback_args.client_handle = client; if (s->state & SOCKET_CARDBUS) client->state |= CLIENT_CARDBUS; if ((!(s->state & SOCKET_CARDBUS)) && (s->functions == 0) && (client->Function != BIND_FN_ALL)) { cistpl_longlink_mfc_t mfc; if (read_tuple(client, CISTPL_LONGLINK_MFC, &mfc) == CS_SUCCESS) s->functions = mfc.nfn; else s->functions = 1; s->config = kmalloc(sizeof(config_t) * s->functions, GFP_KERNEL); if (!s->config) goto out_no_resource; memset(s->config, 0, sizeof(config_t) * s->functions); } cs_dbg(s, 1, "register_client(): client 0x%p, dev %s\n", client, client->dev_info); if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE) EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW); if ((s->state & (SOCKET_PRESENT|SOCKET_CARDBUS)) == SOCKET_PRESENT) { if (client->EventMask & CS_EVENT_CARD_INSERTION) EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); else client->PendingEvents |= CS_EVENT_CARD_INSERTION; } up(&s->skt_sem); return CS_SUCCESS; out_no_resource: up(&s->skt_sem); return CS_OUT_OF_RESOURCE;} /* register_client *//*====================================================================*/int pcmcia_release_configuration(client_handle_t handle){ pccard_io_map io = { 0, 0, 0, 0, 1 }; struct pcmcia_socket *s; int i; if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_CONFIG_LOCKED)) return CS_BAD_HANDLE; handle->state &= ~CLIENT_CONFIG_LOCKED; s = SOCKET(handle); #ifdef CONFIG_CARDBUS if (handle->state & CLIENT_CARDBUS) return CS_SUCCESS;#endif if (!(handle->state & CLIENT_STALE)) { config_t *c = CONFIG(handle); if (--(s->lock_count) == 0) { s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */ s->socket.Vpp = 0; s->socket.io_irq = 0; s->ops->set_socket(s, &s->socket); } if (c->state & CONFIG_IO_REQ) for (i = 0; i < MAX_IO_WIN; i++) { if (s->io[i].NumPorts == 0) continue; s->io[i].Config--; if (s->io[i].Config != 0) continue; io.map = i; s->ops->set_io_map(s, &io); } c->state &= ~CONFIG_LOCKED; } return CS_SUCCESS;} /* release_configuration *//*====================================================================== Release_io() releases the I/O ranges allocated by a client. This may be invoked some time after a card ejection has already dumped the actual socket configuration, so if the client is "stale", we don't bother checking the port ranges against the current socket values. ======================================================================*/int pcmcia_release_io(client_handle_t handle, io_req_t *req){ struct pcmcia_socket *s; if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IO_REQ)) return CS_BAD_HANDLE; handle->state &= ~CLIENT_IO_REQ; s = SOCKET(handle); #ifdef CONFIG_CARDBUS if (handle->state & CLIENT_CARDBUS) return CS_SUCCESS;#endif if (!(handle->state & CLIENT_STALE)) { config_t *c = CONFIG(handle); if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if ((c->io.BasePort1 != req->BasePort1) || (c->io.NumPorts1 != req->NumPorts1) || (c->io.BasePort2 != req->BasePort2) || (c->io.NumPorts2 != req->NumPorts2)) return CS_BAD_ARGS; c->state &= ~CONFIG_IO_REQ; } release_io_space(s, req->BasePort1, req->NumPorts1); if (req->NumPorts2) release_io_space(s, req->BasePort2, req->NumPorts2); return CS_SUCCESS;} /* release_io *//*====================================================================*/int pcmcia_release_irq(client_handle_t handle, irq_req_t *req){ struct pcmcia_socket *s; if (CHECK_HANDLE(handle) || !(handle->state & CLIENT_IRQ_REQ)) return CS_BAD_HANDLE; handle->state &= ~CLIENT_IRQ_REQ; s = SOCKET(handle); if (!(handle->state & CLIENT_STALE)) { config_t *c = CONFIG(handle); if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if (c->irq.Attributes != req->Attributes) return CS_BAD_ATTRIBUTE; if (s->irq.AssignedIRQ != req->AssignedIRQ) return CS_BAD_IRQ; if (--s->irq.Config == 0) { c->state &= ~CONFIG_IRQ_REQ; s->irq.AssignedIRQ = 0; } } if (req->Attributes & IRQ_HANDLE_PRESENT) { free_irq(req->AssignedIRQ, req->Instance); }#ifdef CONFIG_PCMCIA_PROBE if (req->AssignedIRQ != s->pci_irq) undo_irq(req->Attributes, req->AssignedIRQ);#endif return CS_SUCCESS;} /* cs_release_irq *//*====================================================================*/int pcmcia_release_window(window_handle_t win){ struct pcmcia_socket *s; if ((win == NULL) || (win->magic != WINDOW_MAGIC)) return CS_BAD_HANDLE; s = win->sock; if (!(win->handle->state & CLIENT_WIN_REQ(win->index))) return CS_BAD_HANDLE; /* Shut down memory window */ win->ctl.flags &= ~MAP_ACTIVE; s->ops->set_mem_map(s, &win->ctl); s->state &= ~SOCKET_WIN_REQ(win->index); /* Release system memory */ if (win->ctl.res) { release_resource(win->ctl.res); kfree(win->ctl.res); win->ctl.res = NULL; } win->handle->state &= ~CLIENT_WIN_REQ(win->index); win->magic = 0; return CS_SUCCESS;} /* release_window *//*====================================================================*/int pcmcia_request_configuration(client_handle_t handle, config_req_t *req){ int i; u_int base; struct pcmcia_socket *s; config_t *c; pccard_io_map iomap; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; #ifdef CONFIG_CARDBUS if (handle->state & CLIENT_CARDBUS) return CS_UNSUPPORTED_MODE;#endif if (req->IntType & INT_CARDBUS) return CS_UNSUPPORTED_MODE; c = CONFIG(handle); if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; /* Do power control. We don't allow changes in Vcc. */ if (s->socket.Vcc != req->Vcc) return CS_BAD_VCC; if (req->Vpp1 != req->Vpp2) return CS_BAD_VPP; s->socket.Vpp = req->Vpp1; if (s->ops->set_socket(s, &s->socket)) return CS_BAD_VPP; c->Vcc = req->Vcc; c->Vpp1 = c->Vpp2 = req->Vpp1; /* Pick memory or I/O card, DMA mode, interrupt */ c->IntType = req->IntType; c->Attributes = req->Attributes; if (req->IntType & INT_MEMORY_AND_IO) s->socket.flags |= SS_IOCARD; if (req->IntType & INT_ZOOMED_VIDEO) s->socket.flags |= SS_ZVCARD | SS_IOCARD; if (req->Attributes & CONF_ENABLE_DMA) s->socket.flags |= SS_DMA_MODE; if (req->Attributes & CONF_ENABLE_SPKR) s->socket.flags |= SS_SPKR_ENA; if (req->Attributes & CONF_ENABLE_IRQ) s->socket.io_irq = s->irq.AssignedIRQ; else s->socket.io_irq = 0; s->ops->set_socket(s, &s->socket); s->lock_count++; /* Set up CIS configuration registers */ base = c->ConfigBase = req->ConfigBase; c->Present = c->CardValues = req->Present; if (req->Present & PRESENT_COPY) { c->Copy = req->Copy; write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &c->Copy); } if (req->Present & PRESENT_OPTION) { if (s->functions == 1) { c->Option = req->ConfigIndex & COR_CONFIG_MASK; } else { c->Option = req->ConfigIndex & COR_MFC_CONFIG_MASK; c->Option |= COR_FUNC_ENA|COR_IREQ_ENA; if (req->Present & PRESENT_IOBASE_0) c->Option |= COR_ADDR_DECODE; } if (c->state & CONFIG_IRQ_REQ) if (!(c->irq.Attributes & IRQ_FORCED_PULSE)) c->Option |= COR_LEVEL_REQ; write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &c->Option); mdelay(40); } if (req->Present & PRESENT_STATUS) { c->Status = req->Status;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?