⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cs.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
static void cs_sleep(unsigned int n_cs){	current->state = TASK_INTERRUPTIBLE;	schedule_timeout( (n_cs * HZ + 99) / 100);}static void shutdown_socket(socket_info_t *s){    client_t **c;        DEBUG(1, "cs: shutdown_socket(%p)\n", s);    /* Blank out the socket state */    s->state &= SOCKET_PRESENT|SOCKET_SETUP_PENDING;    init_socket(s);    s->irq.AssignedIRQ = s->irq.Config = 0;    s->lock_count = 0;    s->cis_used = 0;    if (s->fake_cis) {	kfree(s->fake_cis);	s->fake_cis = NULL;    }#ifdef CONFIG_CARDBUS    cb_release_cis_mem(s);    cb_free(s);#endif    s->functions = 0;    if (s->config) {	kfree(s->config);	s->config = NULL;    }    for (c = &s->clients; *c; ) {	if ((*c)->state & CLIENT_UNBOUND) {	    client_t *d = *c;	    *c = (*c)->next;	    kfree(d);	} else {	    c = &((*c)->next);	}    }    free_regions(&s->a_region);    free_regions(&s->c_region);} /* shutdown_socket *//* * Return zero if we think the card isn't actually present */static int setup_socket(socket_info_t *s){	int val, ret;	int setup_timeout = 100;	/* Wait for "not pending" */	for (;;) {		get_socket_status(s, &val);		if (!(val & SS_PENDING))			break;		if (--setup_timeout) {			cs_sleep(10);			continue;		}		printk(KERN_NOTICE "cs: socket %p voltage interrogation"			" timed out\n", s);		ret = 0;		goto out;	}	if (val & SS_DETECT) {		DEBUG(1, "cs: setup_socket(%p): applying power\n", s);		s->state |= SOCKET_PRESENT;		s->socket.flags &= SS_DEBOUNCED;		if (val & SS_3VCARD)		    s->socket.Vcc = s->socket.Vpp = 33;		else if (!(val & SS_XVCARD))		    s->socket.Vcc = s->socket.Vpp = 50;		else {		    printk(KERN_NOTICE "cs: socket %p: unsupported "			   "voltage key\n", s);		    s->socket.Vcc = 0;		}		if (val & SS_CARDBUS) {		    s->state |= SOCKET_CARDBUS;#ifndef CONFIG_CARDBUS		    printk(KERN_NOTICE "cs: unsupported card type detected!\n");#endif		}		set_socket(s, &s->socket);		cs_sleep(vcc_settle);		reset_socket(s);		ret = 1;	} else {		DEBUG(0, "cs: setup_socket(%p): no card!\n", s);		ret = 0;	}out:	return ret;} /* setup_socket *//*======================================================================    Reset_socket() and unreset_socket() handle hard resets.  Resets    have several causes: card insertion, a call to reset_socket, or    recovery from a suspend/resume cycle.  Unreset_socket() sends    a CS event that matches the cause of the reset.    ======================================================================*/static void reset_socket(socket_info_t *s){    DEBUG(1, "cs: resetting socket %p\n", s);    s->socket.flags |= SS_OUTPUT_ENA | SS_RESET;    set_socket(s, &s->socket);    udelay((long)reset_time);    s->socket.flags &= ~SS_RESET;    set_socket(s, &s->socket);    cs_sleep(unreset_delay);    unreset_socket(s);} /* reset_socket */#define EVENT_MASK \(SOCKET_SETUP_PENDING|SOCKET_SUSPEND|SOCKET_RESET_PENDING)static void unreset_socket(socket_info_t *s){	int setup_timeout = unreset_limit;	int val;	/* Wait for "ready" */	for (;;) {		get_socket_status(s, &val);		if (val & SS_READY)			break;		DEBUG(2, "cs: socket %d not ready yet\n", s->sock);		if (--setup_timeout) {			cs_sleep(unreset_check);			continue;		}		printk(KERN_NOTICE "cs: socket %p timed out during"			" reset.  Try increasing setup_delay.\n", s);		s->state &= ~EVENT_MASK;		return;	}	DEBUG(1, "cs: reset done on socket %p\n", s);	if (s->state & SOCKET_SUSPEND) {	    s->state &= ~EVENT_MASK;	    if (verify_cis_cache(s) != 0)		parse_events(s, SS_DETECT);	    else		send_event(s, CS_EVENT_PM_RESUME, CS_EVENT_PRI_LOW);	} else if (s->state & SOCKET_SETUP_PENDING) {#ifdef CONFIG_CARDBUS	    if (s->state & SOCKET_CARDBUS)		cb_alloc(s);#endif	    send_event(s, CS_EVENT_CARD_INSERTION, CS_EVENT_PRI_LOW);	    s->state &= ~SOCKET_SETUP_PENDING;	} else {	    send_event(s, CS_EVENT_CARD_RESET, CS_EVENT_PRI_LOW);	    if (s->reset_handle) { 		    s->reset_handle->event_callback_args.info = NULL;		    EVENT(s->reset_handle, CS_EVENT_RESET_COMPLETE,			  CS_EVENT_PRI_LOW);	    }	    s->state &= ~EVENT_MASK;	}} /* unreset_socket *//*======================================================================    The central event handler.  Send_event() sends an event to all    valid clients.  Parse_events() interprets the event bits from    a card status change report.  Do_shotdown() handles the high    priority stuff associated with a card removal.    ======================================================================*/static int send_event(socket_info_t *s, event_t event, int priority){    client_t *client = s->clients;    int ret;    DEBUG(1, "cs: send_event(sock %d, event %d, pri %d)\n",	  s->sock, event, priority);    ret = 0;    for (; client; client = client->next) { 	if (client->state & (CLIENT_UNBOUND|CLIENT_STALE))	    continue;	if (client->EventMask & event) {	    ret = EVENT(client, event, priority);	    if (ret != 0)		return ret;	}    }    return ret;} /* send_event */static void do_shutdown(socket_info_t *s){    client_t *client;    if (s->state & SOCKET_SHUTDOWN_PENDING)	return;    s->state |= SOCKET_SHUTDOWN_PENDING;    send_event(s, CS_EVENT_CARD_REMOVAL, CS_EVENT_PRI_HIGH);    for (client = s->clients; client; client = client->next)	if (!(client->Attributes & INFO_MASTER_CLIENT))	    client->state |= CLIENT_STALE;    if (s->state & (SOCKET_SETUP_PENDING|SOCKET_RESET_PENDING)) {	DEBUG(0, "cs: flushing pending setup\n");	s->state &= ~EVENT_MASK;    }    cs_sleep(shutdown_delay);    s->state &= ~SOCKET_PRESENT;    shutdown_socket(s);}static void parse_events(void *info, u_int events){    socket_info_t *s = info;    if (events & SS_DETECT) {	int status;	get_socket_status(s, &status);	if ((s->state & SOCKET_PRESENT) &&	    (!(s->state & SOCKET_SUSPEND) ||	     !(status & SS_DETECT)))	    do_shutdown(s);	if (status & SS_DETECT) {	    if (s->state & SOCKET_SETUP_PENDING) {		DEBUG(1, "cs: delaying pending setup\n");		return;	    }	    s->state |= SOCKET_SETUP_PENDING;	    if (s->state & SOCKET_SUSPEND)		cs_sleep(resume_delay);	    else		cs_sleep(setup_delay);	    s->socket.flags |= SS_DEBOUNCED;	    if (setup_socket(s) == 0)		s->state &= ~SOCKET_SETUP_PENDING;	    s->socket.flags &= ~SS_DEBOUNCED;	}    }    if (events & SS_BATDEAD)	send_event(s, CS_EVENT_BATTERY_DEAD, CS_EVENT_PRI_LOW);    if (events & SS_BATWARN)	send_event(s, CS_EVENT_BATTERY_LOW, CS_EVENT_PRI_LOW);    if (events & SS_READY) {	if (!(s->state & SOCKET_RESET_PENDING))	    send_event(s, CS_EVENT_READY_CHANGE, CS_EVENT_PRI_LOW);	else DEBUG(1, "cs: ready change during reset\n");    }} /* parse_events *//*======================================================================    Another event handler, for power management events.    This does not comply with the latest PC Card spec for handling    power management events.    ======================================================================*/void pcmcia_suspend_socket (socket_info_t *s){    if ((s->state & SOCKET_PRESENT) && !(s->state & SOCKET_SUSPEND)) {	send_event(s, CS_EVENT_PM_SUSPEND, CS_EVENT_PRI_LOW);	suspend_socket(s);	s->state |= SOCKET_SUSPEND;    }}void pcmcia_resume_socket (socket_info_t *s){    int	stat;    /* Do this just to reinitialize the socket */    init_socket(s);    get_socket_status(s, &stat);    /* If there was or is a card here, we need to do something    about it... but parse_events will sort it all out. */    if ((s->state & SOCKET_PRESENT) || (stat & SS_DETECT))	parse_events(s, SS_DETECT);}static int handle_pm_event(struct pm_dev *dev, pm_request_t rqst, void *data){    int i;    socket_info_t *s;    /* only for busses that don't suspend/resume slots directly */    switch (rqst) {    case PM_SUSPEND:	DEBUG(1, "cs: received suspend notification\n");	for (i = 0; i < sockets; i++) {	    s = socket_table [i];	    if (!s->use_bus_pm)		pcmcia_suspend_socket (socket_table [i]);	}	break;    case PM_RESUME:	DEBUG(1, "cs: received resume notification\n");	for (i = 0; i < sockets; i++) {	    s = socket_table [i];	    if (!s->use_bus_pm)		pcmcia_resume_socket (socket_table [i]);	}	break;    }    return 0;} /* handle_pm_event *//*======================================================================    Special stuff for managing IO windows, because they are scarce.    ======================================================================*/static int alloc_io_space(socket_info_t *s, u_int attr, ioaddr_t *base,			  ioaddr_t num, u_int lines, char *name){    int i;    ioaddr_t try, align;    align = (*base) ? (lines ? 1<<lines : 0) : 1;    if (align && (align < num)) {	if (*base) {	    DEBUG(0, "odd IO request: num %04x align %04x\n",		  num, align);	    align = 0;	} else	    while (align && (align < num)) align <<= 1;    }    if (*base & ~(align-1)) {	DEBUG(0, "odd IO request: base %04x align %04x\n",	      *base, align);	align = 0;    }    /* Check for an already-allocated window that must conflict with       what was asked for.  It is a hack because it does not catch all       potential conflicts, just the most obvious ones. */    for (i = 0; i < MAX_IO_WIN; i++)	if ((s->io[i].NumPorts != 0) &&	    ((s->io[i].BasePort & (align-1)) == *base))	    return 1;    for (i = 0; i < MAX_IO_WIN; i++) {	if (s->io[i].NumPorts == 0) {	    if (find_io_region(base, num, align, name) == 0) {		s->io[i].Attributes = attr;		s->io[i].BasePort = *base;		s->io[i].NumPorts = s->io[i].InUse = num;		break;	    } else		return 1;	} else if (s->io[i].Attributes != attr)	    continue;	/* Try to extend top of window */	try = s->io[i].BasePort + s->io[i].NumPorts;	if ((*base == 0) || (*base == try))	    if (find_io_region(&try, num, 0, name) == 0) {		*base = try;		s->io[i].NumPorts += num;		s->io[i].InUse += num;		break;	    }	/* Try to extend bottom of window */	try = s->io[i].BasePort - num;	if ((*base == 0) || (*base == try))	    if (find_io_region(&try, num, 0, name) == 0) {		s->io[i].BasePort = *base = try;		s->io[i].NumPorts += num;		s->io[i].InUse += num;		break;	    }    }    return (i == MAX_IO_WIN);} /* alloc_io_space */static void release_io_space(socket_info_t *s, ioaddr_t base,			     ioaddr_t num){    int i;    release_region(base, num);    for (i = 0; i < MAX_IO_WIN; i++) {	if ((s->io[i].BasePort <= base) &&	    (s->io[i].BasePort+s->io[i].NumPorts >= base+num)) {	    s->io[i].InUse -= num;	    /* Free the window if no one else is using it */	    if (s->io[i].InUse == 0)		s->io[i].NumPorts = 0;	}    }}/*======================================================================    Access_configuration_register() reads and writes configuration    registers in attribute memory.  Memory window 0 is reserved for    this and the tuple reading services.    ======================================================================*/int pcmcia_access_configuration_register(client_handle_t handle,					 conf_reg_t *reg){    socket_info_t *s;    config_t *c;    int addr;    u_char val;        if (CHECK_HANDLE(handle))	return CS_BAD_HANDLE;    s = SOCKET(handle);    if (handle->Function == BIND_FN_ALL) {	if (reg->Function >= s->functions)	    return CS_BAD_ARGS;	c = &s->config[reg->Function];    } else	c = CONFIG(handle);    if (!(c->state & CONFIG_LOCKED))	return CS_CONFIGURATION_LOCKED;    addr = (c->ConfigBase + reg->Offset) >> 1;        switch (reg->Action) {    case CS_READ:	read_cis_mem(s, 1, addr, 1, &val);	reg->Value = val;	break;    case CS_WRITE:	val = reg->Value;	write_cis_mem(s, 1, addr, 1, &val);	break;    default:	return CS_BAD_ARGS;	break;    }    return CS_SUCCESS;} /* access_configuration_register *//*======================================================================    Bind_device() associates a device driver with a particular socket.    It is normally called by Driver Services after it has identified    a newly inserted card.  An instance of that driver will then be    eligible to register as a client of this socket.    ======================================================================*/int pcmcia_bind_device(bind_req_t *req)

⌨️ 快捷键说明

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