📄 cs.c
字号:
(req->Attributes2 & (IO_SHARED | IO_FORCE_ALIAS_ACCESS))) return CS_BAD_ATTRIBUTE; if (alloc_io_space(s, req->Attributes1, &req->BasePort1, req->NumPorts1, req->IOAddrLines, handle->dev_info)) return CS_IN_USE; if (req->NumPorts2) { if (alloc_io_space(s, req->Attributes2, &req->BasePort2, req->NumPorts2, req->IOAddrLines, handle->dev_info)) { release_io_space(s, req->BasePort1, req->NumPorts1); return CS_IN_USE; } } c->io = *req; c->state |= CONFIG_IO_REQ; handle->state |= CLIENT_IO_REQ; return CS_SUCCESS;} /* request_io *//*====================================================================== Request_irq() reserves an irq for this client. Also, since Linux only reserves irq's when they are actually hooked, we don't guarantee that an irq will still be available when the configuration is locked. Now that I think about it, there might be a way to fix this using a dummy handler. ======================================================================*/int pcmcia_request_irq(client_handle_t handle, irq_req_t *req){ socket_info_t *s; config_t *c; int ret = 0, irq = 0; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; s = SOCKET(handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; c = CONFIG(handle); if (c->state & CONFIG_LOCKED) return CS_CONFIGURATION_LOCKED; if (c->state & CONFIG_IRQ_REQ) return CS_IN_USE; /* Short cut: if there are no ISA interrupts, then it is PCI */ if (!s->cap.irq_mask) { irq = s->cap.pci_irq; ret = (irq) ? 0 : CS_IN_USE;#ifdef CONFIG_ISA } else if (s->irq.AssignedIRQ != 0) { /* If the interrupt is already assigned, it must match */ irq = s->irq.AssignedIRQ; if (req->IRQInfo1 & IRQ_INFO2_VALID) { u_int mask = req->IRQInfo2 & s->cap.irq_mask; ret = ((mask >> irq) & 1) ? 0 : CS_BAD_ARGS; } else ret = ((req->IRQInfo1&IRQ_MASK) == irq) ? 0 : CS_BAD_ARGS; } else { ret = CS_IN_USE; if (req->IRQInfo1 & IRQ_INFO2_VALID) { u_int try, mask = req->IRQInfo2 & s->cap.irq_mask; for (try = 0; try < 2; try++) { for (irq = 0; irq < 32; irq++) if ((mask >> irq) & 1) { ret = try_irq(req->Attributes, irq, try); if (ret == 0) break; } if (ret == 0) break; } } else { irq = req->IRQInfo1 & IRQ_MASK; ret = try_irq(req->Attributes, irq, 1); }#endif } if (ret != 0) return ret; if (req->Attributes & IRQ_HANDLE_PRESENT) { if (bus_request_irq(s->cap.bus, irq, req->Handler, ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || (s->functions > 1) || (irq == s->cap.pci_irq)) ? SA_SHIRQ : 0, handle->dev_info, req->Instance)) return CS_IN_USE; } c->irq.Attributes = req->Attributes; s->irq.AssignedIRQ = req->AssignedIRQ = irq; s->irq.Config++; c->state |= CONFIG_IRQ_REQ; handle->state |= CLIENT_IRQ_REQ; return CS_SUCCESS;} /* pcmcia_request_irq *//*====================================================================== Request_window() establishes a mapping between card memory space and system memory space.======================================================================*/int pcmcia_request_window(client_handle_t *handle, win_req_t *req, window_handle_t *wh){ socket_info_t *s; window_t *win; u_long align; int w; if (CHECK_HANDLE(*handle)) return CS_BAD_HANDLE; s = SOCKET(*handle); if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (req->Attributes & (WIN_PAGED | WIN_SHARED)) return CS_BAD_ATTRIBUTE; /* Window size defaults to smallest available */ if (req->Size == 0) req->Size = s->cap.map_size; align = (((s->cap.features & SS_CAP_MEM_ALIGN) || (req->Attributes & WIN_STRICT_ALIGN)) ? req->Size : s->cap.map_size); if (req->Size & (s->cap.map_size-1)) return CS_BAD_SIZE; if ((req->Base && (s->cap.features & SS_CAP_STATIC_MAP)) || (req->Base & (align-1))) return CS_BAD_BASE; if (req->Base) align = 0; /* Allocate system memory window */ for (w = 0; w < MAX_WIN; w++) if (!(s->state & SOCKET_WIN_REQ(w))) break; if (w == MAX_WIN) return CS_OUT_OF_RESOURCE; win = &s->win[w]; win->magic = WINDOW_MAGIC; win->index = w; win->handle = *handle; win->sock = s; win->base = req->Base; win->size = req->Size; if (!(s->cap.features & SS_CAP_STATIC_MAP) && find_mem_region(&win->base, win->size, align, (req->Attributes & WIN_MAP_BELOW_1MB) || !(s->cap.features & SS_CAP_PAGE_REGS), (*handle)->dev_info)) return CS_IN_USE; (*handle)->state |= CLIENT_WIN_REQ(w); /* Configure the socket controller */ win->ctl.map = w+1; win->ctl.flags = 0; win->ctl.speed = req->AccessSpeed; 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.sys_start = win->base; win->ctl.sys_stop = win->base + win->size-1; win->ctl.card_start = 0; if (set_mem_map(s, &win->ctl) != 0) return CS_BAD_ARGS; s->state |= SOCKET_WIN_REQ(w); /* Return window handle */ req->Base = win->ctl.sys_start; *wh = win; return CS_SUCCESS;} /* request_window *//*====================================================================== I'm not sure which "reset" function this is supposed to use, but for now, it uses the low-level interface's reset, not the CIS register. ======================================================================*/int pcmcia_reset_card(client_handle_t handle, client_req_t *req){ int i, ret; socket_info_t *s; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; i = handle->Socket; s = socket_table[i]; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (s->state & SOCKET_RESET_PENDING) return CS_IN_USE; s->state |= SOCKET_RESET_PENDING; ret = send_event(s, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW); if (ret != 0) { s->state &= ~SOCKET_RESET_PENDING; handle->event_callback_args.info = (void *)(u_long)ret; EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW); } else { DEBUG(1, "cs: resetting socket %d\n", i); send_event(s, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW); s->reset_handle = handle; reset_socket(s); } return CS_SUCCESS;} /* reset_card *//*====================================================================== These shut down or wake up a socket. They are sort of user initiated versions of the APM suspend and resume actions. ======================================================================*/int pcmcia_suspend_card(client_handle_t handle, client_req_t *req){ int i; socket_info_t *s; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; i = handle->Socket; s = socket_table[i]; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (s->state & SOCKET_SUSPEND) return CS_IN_USE; DEBUG(1, "cs: suspending socket %d\n", i); send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW); suspend_socket(s); s->state |= SOCKET_SUSPEND; return CS_SUCCESS;} /* suspend_card */int pcmcia_resume_card(client_handle_t handle, client_req_t *req){ int i; socket_info_t *s; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; i = handle->Socket; s = socket_table[i]; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; if (!(s->state & SOCKET_SUSPEND)) return CS_IN_USE; DEBUG(1, "cs: waking up socket %d\n", i); setup_socket(s); return CS_SUCCESS;} /* resume_card *//*====================================================================== These handle user requests to eject or insert a card. ======================================================================*/int pcmcia_eject_card(client_handle_t handle, client_req_t *req){ int i, ret; socket_info_t *s; u_long flags; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; i = handle->Socket; s = socket_table[i]; if (!(s->state & SOCKET_PRESENT)) return CS_NO_CARD; DEBUG(1, "cs: user eject request on socket %d\n", i); ret = send_event(s, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW); if (ret != 0) return ret; spin_lock_irqsave(&s->lock, flags); do_shutdown(s); spin_unlock_irqrestore(&s->lock, flags); return CS_SUCCESS; } /* eject_card */int pcmcia_insert_card(client_handle_t handle, client_req_t *req){ int i, status; socket_info_t *s; u_long flags; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; i = handle->Socket; s = socket_table[i]; if (s->state & SOCKET_PRESENT) return CS_IN_USE; DEBUG(1, "cs: user insert request on socket %d\n", i); spin_lock_irqsave(&s->lock, flags); if (!(s->state & SOCKET_SETUP_PENDING)) { s->state |= SOCKET_SETUP_PENDING; spin_unlock_irqrestore(&s->lock, flags); get_socket_status(s, &status); if ((status & SS_DETECT) == 0 || (setup_socket(s) == 0)) { s->state &= ~SOCKET_SETUP_PENDING; return CS_NO_CARD; } } else spin_unlock_irqrestore(&s->lock, flags); return CS_SUCCESS;} /* insert_card *//*====================================================================== Maybe this should send a CS_EVENT_CARD_INSERTION event if we haven't sent one to this client yet? ======================================================================*/int pcmcia_set_event_mask(client_handle_t handle, eventmask_t *mask){ u_int events, bit; if (CHECK_HANDLE(handle)) return CS_BAD_HANDLE; if (handle->Attributes & CONF_EVENT_MASK_VALID) return CS_BAD_SOCKET; handle->EventMask = mask->EventMask; events = handle->PendingEvents & handle->EventMask; handle->PendingEvents -= events; while (events != 0) { bit = ((events ^ (events-1)) + 1) >> 1; EVENT(handle, bit, CS_EVENT_PRI_LOW); events -= bit; } return CS_SUCCESS;} /* set_event_mask *//*====================================================================*/int pcmcia_report_error(client_handle_t handle, error_info_t *err){ int i; char *serv; if (CHECK_HANDLE(handle)) printk(KERN_NOTICE); else printk(KERN_NOTICE "%s: ", handle->dev_info); for (i = 0; i < SERVICE_COUNT; i++) if (service_table[i].key == err->func) break; if (i < SERVICE_COUNT) serv = service_table[i].msg; else serv = "Unknown service number"; for (i = 0; i < ERROR_COUNT; i++) if (error_table[i].key == err->retcode) break; if (i < ERROR_COUNT) printk("%s: %s\n", serv, error_table[i].msg); else printk("%s: Unknown error code %#x\n", serv, err->retcode); return CS_SUCCESS;} /* report_error *//*====================================================================*/int CardServices(int func, void *a1, void *a2, void *a3){#ifdef PCMCIA_DEBUG if (pc_debug > 2) { int i; for (i = 0; i < SERVICE_COUNT; i++) if (service_table[i].key == func) break; if (i < SERVICE_COUNT) printk(KERN_DEBUG "cs: CardServices(%s, 0x%p, 0x%p)\n", service_table[i].msg, a1, a2); else printk(KERN_DEBUG "cs: CardServices(Unknown func %d, " "0x%p, 0x%p)\n", func, a1, a2); }#endif switch (func) { case AccessConfigurationRegister: return pcmcia_access_configuration_register(a1, a2); break; case AdjustResourceInfo: return pcmcia_adjust_resource_info(a1, a2); break; case CheckEraseQueue: return pcmcia_check_erase_queue(a1); break; case CloseMemory: return pcmcia_close_memory(a1); break; case CopyMemory: return pcmcia_copy_memory(a1, a2); break; case DeregisterClient: return pcmcia_deregister_client(a1); break; case DeregisterEraseQueue: return pcmcia_deregister_erase_queue(a1); break; case GetFirstClient: return pcmcia_get_first_client(a1, a2); break; case GetCardServicesInfo: return pcmcia_get_card_services_info(a1); break; case GetConfigurationInfo: return pcmcia_get_configuration_info(a1, a2); break; case GetNextClient: return pcmcia_get_next_client(a1, a2); break; case GetFirstRegion: return pcmcia_get_first_region(a1, a2); break; case GetFirstTuple: return pcmcia_get_first_tuple(a1, a2); break; case GetNextRegion: return pcmcia_get_next_region(a1, a2); break; case GetNextTuple: return pcmcia_get_next_tuple(a1, a2); break; case GetStatus: return pcmcia_get_status(a1, a2); break; case GetTupleData: return pcmcia_get_tuple_data(a1, a2); break; case MapMemPage: return pcmcia_map_mem_page(a1, a2); break; case ModifyConfiguration: return pcmcia_modify_configuration(a1, a2); break; case ModifyWindow: return pcmcia_modify_window(a1, a2); break; case OpenMemory:/* return pcmcia_open_memory(a1, a2); */ { memory
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -