📄 cs.c
字号:
/* 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 (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; 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; socket_info_t *s; socket_t ns; /* Look for unbound client with matching dev_info */ client = NULL; for (ns = 0; ns < sockets; ns++) { client = socket_table[ns]->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; } if (client == NULL) return CS_OUT_OF_RESOURCE; s = socket_table[ns]; if (++s->real_clients == 1) { int status; register_callback(s, &parse_events, s); get_socket_status(s, &status); if ((status & SS_DETECT) && !(s->state & SOCKET_SETUP_PENDING)) { s->state |= SOCKET_SETUP_PENDING; if (setup_socket(s) == 0) s->state &= ~SOCKET_SETUP_PENDING; } } *handle = client; client->state &= ~CLIENT_UNBOUND; client->Socket = ns; 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; client->event_callback_args.bus = s->cap.bus; 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); memset(s->config, 0, sizeof(config_t) * s->functions); } DEBUG(1, "cs: register_client(): client 0x%p, sock %d, dev %s\n", client, client->Socket, client->dev_info); if (client->EventMask & CS_EVENT_REGISTRATION_COMPLETE) EVENT(client, CS_EVENT_REGISTRATION_COMPLETE, CS_EVENT_PRI_LOW); if ((socket_table[ns]->state & SOCKET_PRESENT) && !(socket_table[ns]->state & SOCKET_SETUP_PENDING)) { if (client->EventMask & CS_EVENT_CARD_INSERTION) EVENT(client, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW); else client->PendingEvents |= CS_EVENT_CARD_INSERTION; } return CS_SUCCESS;} /* register_client *//*====================================================================*/int pcmcia_release_configuration(client_handle_t handle){ pccard_io_map io = { 0, 0, 0, 0, 1 }; socket_info_t *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) { cb_disable(s); s->lock_count = 0; 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; s->socket.Vpp = 0; s->socket.io_irq = 0; 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; 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){ socket_info_t *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) { cb_release(s); 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){ socket_info_t *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) { bus_free_irq(s->cap.bus, req->AssignedIRQ, req->Instance); }#ifdef CONFIG_ISA if (req->AssignedIRQ != s->cap.pci_irq) undo_irq(req->Attributes, req->AssignedIRQ);#endif return CS_SUCCESS;} /* cs_release_irq *//*====================================================================*/int pcmcia_release_window(window_handle_t win){ socket_info_t *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; set_mem_map(s, &win->ctl); s->state &= ~SOCKET_WIN_REQ(win->index); /* Release system memory */ release_mem_region(win->base, win->size); 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; socket_info_t *s; config_t *c; pccard_io_map iomap; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; i = handle->Socket; s = socket_table[i]; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; #ifdef CONFIG_CARDBUS if (handle->state & CLIENT_CARDBUS) { if (!(req->IntType & INT_CARDBUS)) return CS_UNSUPPORTED_MODE; if (s->lock_count != 0) return CS_CONFIGURATION_LOCKED; cb_enable(s); handle->state |= CLIENT_CONFIG_LOCKED; s->lock_count++; return CS_SUCCESS; }#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 (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->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; 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; write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &c->Status); } if (req->Present & PRESENT_PIN_REPLACE) { c->Pin = req->Pin; write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &c->Pin); } if (req->Present & PRESENT_EXT_STATUS) { c->ExtStatus = req->ExtStatus; write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1, &c->ExtStatus); } if (req->Present & PRESENT_IOBASE_0) { u_char b = c->io.BasePort1 & 0xff; write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b); b = (c->io.BasePort1 >> 8) & 0xff; write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b); } if (req->Present & PRESENT_IOSIZE) { u_char b = c->io.NumPorts1 + c->io.NumPorts2 - 1; write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b); } /* Configure I/O windows */ if (c->state & CONFIG_IO_REQ) { iomap.speed = io_speed; for (i = 0; i < MAX_IO_WIN; i++) if (s->io[i].NumPorts != 0) { iomap.map = i; iomap.flags = MAP_ACTIVE; switch (s->io[i].Attributes & IO_DATA_PATH_WIDTH) { case IO_DATA_PATH_WIDTH_16: iomap.flags |= MAP_16BIT; break; case IO_DATA_PATH_WIDTH_AUTO: iomap.flags |= MAP_AUTOSZ; break; default: break; } iomap.start = s->io[i].BasePort; iomap.stop = iomap.start + s->io[i].NumPorts - 1; set_io_map(s, &iomap); s->io[i].Config++; } } c->state |= CONFIG_LOCKED; handle->state |= CLIENT_CONFIG_LOCKED; return CS_SUCCESS;} /* request_configuration *//*====================================================================== Request_io() reserves ranges of port addresses for a socket. I have not implemented range sharing or alias addressing. ======================================================================*/int pcmcia_request_io(client_handle_t handle, io_req_t *req){ 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->state & CLIENT_CARDBUS) {#ifdef CONFIG_CARDBUS int ret = cb_config(s); if (ret == CS_SUCCESS) handle->state |= CLIENT_IO_REQ; return ret;#else return CS_UNSUPPORTED_FUNCTION;#endif } if (!req) return CS_UNSUPPORTED_MODE; c = CONFIG(handle); if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if (c->state & CONFIG_IO_REQ) return CS_IN_USE; if (req->Attributes1 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS)) return CS_BAD_ATTRIBUTE; if ((req->NumPorts2 > 0) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -