cs.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,183 行 · 第 1/4 页

C
2,183
字号
	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;		s->ops->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){    struct pcmcia_socket *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	handle->state |= CLIENT_IO_REQ;	return CS_SUCCESS;#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) &&	(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){    struct pcmcia_socket *s;    config_t *c;    int ret = CS_IN_USE, 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;#ifdef CONFIG_PCMCIA_PROBE    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->irq_mask;	    ret = ((mask >> irq) & 1) ? 0 : CS_BAD_ARGS;	} else	    ret = ((req->IRQInfo1&IRQ_MASK) == irq) ? 0 : CS_BAD_ARGS;    } else {	if (req->IRQInfo1 & IRQ_INFO2_VALID) {	    u_int try, mask = req->IRQInfo2 & s->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) {	if (!s->pci_irq)	    return ret;	irq = s->pci_irq;    }    if (req->Attributes & IRQ_HANDLE_PRESENT) {	if (request_irq(irq, req->Handler,			    ((req->Attributes & IRQ_TYPE_DYNAMIC_SHARING) || 			     (s->functions > 1) ||			     (irq == s->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){    struct pcmcia_socket *s;    window_t *win;    u_long align;    int w;        if (CHECK_HANDLE(*handle))	return CS_BAD_HANDLE;    s = (*handle)->Socket;    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->map_size;    align = (((s->features & SS_CAP_MEM_ALIGN) ||	      (req->Attributes & WIN_STRICT_ALIGN)) ?	     req->Size : s->map_size);    if (req->Size & (s->map_size-1))	return CS_BAD_SIZE;    if ((req->Base && (s->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;    if (!(s->features & SS_CAP_STATIC_MAP)) {	win->ctl.res = find_mem_region(req->Base, req->Size, align,				       (req->Attributes & WIN_MAP_BELOW_1MB),				       (*handle)->dev_info, s);	if (!win->ctl.res)	    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.card_start = 0;    if (s->ops->set_mem_map(s, &win->ctl) != 0)	return CS_BAD_ARGS;    s->state |= SOCKET_WIN_REQ(w);    /* Return window handle */    if (s->features & SS_CAP_STATIC_MAP) {	req->Base = win->ctl.static_start;    } else {	req->Base = win->ctl.res->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){	struct pcmcia_socket *skt;	int ret;    	if (CHECK_HANDLE(handle))		return CS_BAD_HANDLE;	skt = SOCKET(handle);	cs_dbg(skt, 1, "resetting socket\n");	down(&skt->skt_sem);	do {		if (!(skt->state & SOCKET_PRESENT)) {			ret = CS_NO_CARD;			break;		}		if (skt->state & SOCKET_SUSPEND) {			ret = CS_IN_USE;			break;		}		if (skt->state & SOCKET_CARDBUS) {			ret = CS_UNSUPPORTED_FUNCTION;			break;		}		ret = send_event(skt, CS_EVENT_RESET_REQUEST, CS_EVENT_PRI_LOW);		if (ret == 0) {			send_event(skt, CS_EVENT_RESET_PHYSICAL, CS_EVENT_PRI_LOW);			if (socket_reset(skt) == CS_SUCCESS)				send_event(skt, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);		}		handle->event_callback_args.info = (void *)(u_long)ret;		EVENT(handle, CS_EVENT_RESET_COMPLETE, CS_EVENT_PRI_LOW);		ret = CS_SUCCESS;	} while (0);	up(&skt->skt_sem);	return ret;} /* 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(struct pcmcia_socket *skt){	int ret;    	cs_dbg(skt, 1, "suspending socket\n");	down(&skt->skt_sem);	do {		if (!(skt->state & SOCKET_PRESENT)) {			ret = CS_NO_CARD;			break;		}		if (skt->state & SOCKET_CARDBUS) {			ret = CS_UNSUPPORTED_FUNCTION;			break;		}		ret = socket_suspend(skt);	} while (0);	up(&skt->skt_sem);	return ret;} /* suspend_card */int pcmcia_resume_card(struct pcmcia_socket *skt){	int ret;    	cs_dbg(skt, 1, "waking up socket\n");	down(&skt->skt_sem);	do {		if (!(skt->state & SOCKET_PRESENT)) {			ret = CS_NO_CARD;			break;		}		if (skt->state & SOCKET_CARDBUS) {			ret = CS_UNSUPPORTED_FUNCTION;			break;		}		ret = socket_resume(skt);	} while (0);	up(&skt->skt_sem);	return ret;} /* resume_card *//*======================================================================    These handle user requests to eject or insert a card.    ======================================================================*/int pcmcia_eject_card(struct pcmcia_socket *skt){	int ret;    	cs_dbg(skt, 1, "user eject request\n");	down(&skt->skt_sem);	do {		if (!(skt->state & SOCKET_PRESENT)) {			ret = -ENODEV;			break;		}		ret = send_event(skt, CS_EVENT_EJECTION_REQUEST, CS_EVENT_PRI_LOW);		if (ret != 0) {			ret = -EINVAL;			break;		}		socket_remove(skt);		ret = 0;	} while (0);	up(&skt->skt_sem);	return ret;} /* eject_card */int pcmcia_insert_card(struct pcmcia_socket *skt){	int ret;	cs_dbg(skt, 1, "user insert request\n");	down(&skt->skt_sem);	do {		if (skt->state & SOCKET_PRESENT) {			ret = -EBUSY;			break;		}		if (socket_insert(skt) == CS_NO_CARD) {			ret = -ENODEV;			break;		}		ret = 0;	} while (0);	up(&skt->skt_sem);	return ret;} /* 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 *//*======================================================================    OS-specific module glue goes here    ======================================================================*//* in alpha order */EXPORT_SYMBOL(pcmcia_access_configuration_register);EXPORT_SYMBOL(pcmcia_adjust_resource_info);EXPORT_SYMBOL(pcmcia_check_erase_queue);EXPORT_SYMBOL(pcmcia_close_memory);EXPORT_SYMBOL(pcmcia_copy_memory);EXPORT_SYMBOL(pcmcia_deregister_client);EXPORT_SYMBOL(pcmcia_deregister_erase_queue);EXPORT_SYMBOL(pcmcia_eject_card);EXPORT_SYMBOL(pcmcia_get_first_client);EXPORT_SYMBOL(pcmcia_get_card_services_info);EXPORT_SYMBOL(pcmcia_get_configuration_info);EXPORT_SYMBOL(pcmcia_get_mem_page);EXPORT_SYMBOL(pcmcia_get_next_client);EXPORT_SYMBOL(pcmcia_get_first_region);EXPORT_SYMBOL(pcmcia_get_first_tuple);EXPORT_SYMBOL(pcmcia_get_first_window);EXPORT_SYMBOL(pcmcia_get_next_region);EXPORT_SYMBOL(pcmcia_get_next_tuple);EXPORT_SYMBOL(pcmcia_get_next_window);EXPORT_SYMBOL(pcmcia_get_status);EXPORT_SYMBOL(pcmcia_get_tuple_data);EXPORT_SYMBOL(pcmcia_insert_card);EXPORT_SYMBOL(pcmcia_map_mem_page);EXPORT_SYMBOL(pcmcia_modify_configuration);EXPORT_SYMBOL(pcmcia_modify_window);EXPORT_SYMBOL(pcmcia_open_memory);EXPORT_SYMBOL(pcmcia_parse_tuple);EXPORT_SYMBOL(pcmcia_read_memory);EXPORT_SYMBOL(pcmcia_register_client);EXPORT_SYMBOL(pcmcia_register_erase_queue);EXPORT_SYMBOL(pcmcia_register_mtd);EXPORT_SYMBOL(pcmcia_release_configuration);EXPORT_SYMBOL(pcmcia_release_io);EXPORT_SYMBOL(pcmcia_release_irq);EXPORT_SYMBOL(pcmcia_release_window);EXPORT_SYMBOL(pcmcia_replace_cis);EXPORT_SYMBOL(pcmcia_request_configuration);EXPORT_SYMBOL(pcmcia_request_io);EXPORT_SYMBOL(pcmcia_request_irq);EXPORT_SYMBOL(pcmcia_request_window);EXPORT_SYMBOL(pcmcia_reset_card);EXPORT_SYMBOL(pcmcia_resume_card);EXPORT_SYMBOL(pcmcia_set_event_mask);EXPORT_SYMBOL(pcmcia_suspend_card);EXPORT_SYMBOL(pcmcia_validate_cis);EXPORT_SYMBOL(pcmcia_write_memory);EXPORT_SYMBOL(dead_socket);EXPORT_SYMBOL(MTDHelperEntry);EXPORT_SYMBOL(pcmcia_parse_events);struct class pcmcia_socket_class = {	.name = "pcmcia_socket",	.release = pcmcia_release_socket,};EXPORT_SYMBOL(pcmcia_socket_class);static int __init init_pcmcia_cs(void){	int ret;	printk(KERN_INFO "%s\n", release);	printk(KERN_INFO "  %s\n", options);	ret = class_register(&pcmcia_socket_class);	if (ret)		return (ret);	return class_interface_register(&pccard_sysfs_interface);}static void __exit exit_pcmcia_cs(void){    printk(KERN_INFO "unloading Kernel Card Services\n");    release_resource_db();    class_interface_unregister(&pccard_sysfs_interface);    class_unregister(&pcmcia_socket_class);}subsys_initcall(init_pcmcia_cs);module_exit(exit_pcmcia_cs);/*====================================================================*/

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?