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, &reg);	    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, &reg);	    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 + -
显示快捷键?