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

📄 nsp_cs.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
timer_out:	nsp_start_timer(tmpSC, data, 1000/102);	return;}#ifdef PCMCIA_DEBUG#include "nsp_debug.c"#endif	/* DBG_SHOWCOMMAND *//*----------------------------------------------------------------*//* look for ninja3 card and init if found			  *//*----------------------------------------------------------------*/static int nsp_detect(Scsi_Host_Template *sht){	struct Scsi_Host *host;	/* registered host structure */	nsp_hw_data *data = &nsp_data;	DEBUG(0, __FUNCTION__ " this_id=%d\n", sht->this_id);	request_region(data->BaseAddress, data->NumAddress, "nsp_cs");	host		  = scsi_register(sht, 0);	host->io_port	  = data->BaseAddress;	host->unique_id	  = data->BaseAddress;	host->n_io_port	  = data->NumAddress;	host->irq	  = data->IrqNumber;	host->dma_channel = 0xff;             /* not use dms */	sprintf(nspinfo,/* Buffer size is 100 bytes *//*  0         1         2         3         4         5         6         7         8         9         0*//*  01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890*/   "NinjaSCSI-3/32Bi Driver $Revision: 1.42 $, I/O 0x%04lx-0x%04lx IRQ %2d",		host->io_port, host->io_port + host->n_io_port,		host->irq);	sht->name	  = nspinfo;	DEBUG(0, __FUNCTION__ " end\n");	return 1; /* detect done. */}/* nsp_cs requires own release handler because its uses dev_id (=data) */static int nsp_release(struct Scsi_Host *shpnt){	nsp_hw_data *data = &nsp_data;        if (shpnt->irq) {                free_irq(shpnt->irq, data);	}        if (shpnt->io_port && shpnt->n_io_port) {		release_region(shpnt->io_port, shpnt->n_io_port);	}	return 0;}/*----------------------------------------------------------------*//* return info string						  *//*----------------------------------------------------------------*/static const char *nsp_info(struct Scsi_Host *shpnt){	return nspinfo;}/*---------------------------------------------------------------*//* error handler                                                 *//*---------------------------------------------------------------*/static int nsp_reset(Scsi_Cmnd *SCpnt, unsigned int why){	DEBUG(0, __FUNCTION__ " SCpnt=0x%p why=%d\n", SCpnt, why);	nsp_eh_bus_reset(SCpnt);	return SCSI_RESET_SUCCESS;}static int nsp_abort(Scsi_Cmnd *SCpnt){	DEBUG(0, __FUNCTION__ " SCpnt=0x%p\n", SCpnt);	nsp_eh_bus_reset(SCpnt);	return SCSI_ABORT_SUCCESS;}/*static int nsp_eh_strategy(struct Scsi_Host *Shost){	return FAILED;}*/static int nsp_eh_abort(Scsi_Cmnd *SCpnt){	DEBUG(0, __FUNCTION__ " SCpnt=0x%p\n", SCpnt);	nsp_eh_bus_reset(SCpnt);	return SUCCESS;}static int nsp_eh_device_reset(Scsi_Cmnd *SCpnt){	DEBUG(0, __FUNCTION__ " SCpnt=0x%p\n", SCpnt);	return FAILED;}static int nsp_eh_bus_reset(Scsi_Cmnd *SCpnt){	unsigned int base = SCpnt->host->io_port;	int	     i;	DEBUG(0, __FUNCTION__ "() SCpnt=0x%p base=0x%x\n", SCpnt, base);	nsp_write(base, IRQCONTROL, IRQCONTROL_ALLMASK);	nsp_index_write(base, SCSIBUSCTRL, SCSI_RST);	mdelay(100); /* 100ms */	nsp_index_write(base, SCSIBUSCTRL, 0);	for(i = 0; i < 5; i++) {		nsp_index_read(base, IRQPHASESENCE); /* dummy read */	}	nsp_write(base, IRQCONTROL, IRQCONTROL_ALLCLEAR);	return SUCCESS;}static int nsp_eh_host_reset(Scsi_Cmnd *SCpnt){	nsp_hw_data *data = &nsp_data;	DEBUG(0, __FUNCTION__ "\n");	nsphw_init(data);	return nsp_eh_bus_reset(SCpnt);}/**********************************************************************  PCMCIA functions  *********************************************************************//*====================================================================*/static void cs_error(client_handle_t handle, int func, int ret){	error_info_t err = { func, ret };	CardServices(ReportError, handle, &err);}/*======================================================================    nsp_cs_attach() creates an "instance" of the driver, allocating    local data structures for one device.  The device is registered    with Card Services.    The dev_link structure is initialized, but we don't actually    configure the card at this point -- we wait until we receive a    card insertion event.======================================================================*/static dev_link_t *nsp_cs_attach(void){	scsi_info_t  *info;	client_reg_t  client_reg;	dev_link_t   *link;	int	      ret, i;	DEBUG(0, __FUNCTION__ "()\n");	/* Create new SCSI device */	info = kmalloc(sizeof(*info), GFP_KERNEL);	if (!info) { return NULL; }	memset(info, 0, sizeof(*info));	link = &info->link;	link->priv = info;	/* Initialize the dev_link_t structure */	link->release.function	 = &nsp_cs_release;	link->release.data	 = (u_long)link;	/* The io structure describes IO port mapping */	link->io.NumPorts1	 = 0x10;	link->io.Attributes1	 = IO_DATA_PATH_WIDTH_AUTO;	link->io.IOAddrLines	 = 10;	/* not used */	/* Interrupt setup */	link->irq.Attributes	 = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;	link->irq.IRQInfo1	 = IRQ_INFO2_VALID    | IRQ_LEVEL_ID;	if (irq_list[0] == -1) {		link->irq.IRQInfo2 = irq_mask;	} else {		for (i = 0; i < 4; i++) {			link->irq.IRQInfo2 |= 1 << irq_list[i];		}	}	link->irq.Handler	 = &nspintr;	link->irq.Instance       = &nsp_data;	/* General socket configuration */	link->conf.Attributes	 = CONF_ENABLE_IRQ;	link->conf.Vcc		 = 50;	link->conf.IntType	 = INT_MEMORY_AND_IO;	link->conf.Present	 = PRESENT_OPTION;	/* Register with Card Services */	link->next               = dev_list;	dev_list                 = link;	client_reg.dev_info	 = &dev_info;	client_reg.Attributes	 = INFO_IO_CLIENT | INFO_CARD_SHARE;	client_reg.EventMask	 =		CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |		CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET	|		CS_EVENT_PM_SUSPEND	| CS_EVENT_PM_RESUME	 ;	client_reg.event_handler = &nsp_cs_event;	client_reg.Version	 = 0x0210;	client_reg.event_callback_args.client_data = link;	ret = CardServices(RegisterClient, &link->handle, &client_reg);	if (ret != CS_SUCCESS) {		cs_error(link->handle, RegisterClient, ret);		nsp_cs_detach(link);		return NULL;	}	return link;} /* nsp_cs_attach *//*======================================================================    This deletes a driver "instance".  The device is de-registered    with Card Services.	 If it has been released, all local data    structures are freed.  Otherwise, the structures will be freed    when the device is released.======================================================================*/static void nsp_cs_detach(dev_link_t *link){	dev_link_t **linkp;	DEBUG(0, __FUNCTION__ "(0x%p)\n", link);    	/* Locate device structure */	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {		if (*linkp == link) {			break;		}	}	if (*linkp == NULL) {		return;	}	del_timer(&link->release);	if (link->state & DEV_CONFIG) {		nsp_cs_release((u_long)link);		if (link->state & DEV_STALE_CONFIG) {			link->state |= DEV_STALE_LINK;			return;		}	}	/* Break the link with Card Services */	if (link->handle) {		CardServices(DeregisterClient, link->handle);	}	/* Unlink device structure, free bits */	*linkp = link->next;	kfree(link->priv);} /* nsp_cs_detach *//*======================================================================    nsp_cs_config() is scheduled to run after a CARD_INSERTION event    is received, to configure the PCMCIA socket, and to make the    ethernet device available to the system.======================================================================*/#define CS_CHECK(fn, args...) \while ((last_ret=CardServices(last_fn=(fn),args))!=0) goto cs_failed#define CFG_CHECK(fn, args...) \if (CardServices(fn, args) != 0) goto next_entry/*====================================================================*/static void nsp_cs_config(dev_link_t *link){	client_handle_t	  handle = link->handle;	scsi_info_t	 *info	 = link->priv;	tuple_t		  tuple;	cisparse_t	  parse;	int		  i, last_ret, last_fn;	u_char		  tuple_data[64];	config_info_t	  conf;	Scsi_Device	 *dev;	dev_node_t	**tail, *node;	struct Scsi_Host *host;	nsp_hw_data      *data = &nsp_data;	DEBUG(0, __FUNCTION__ "() in\n");	tuple.DesiredTuple    = CISTPL_CONFIG;	tuple.Attributes      = 0;	tuple.TupleData	      = tuple_data;	tuple.TupleDataMax    = sizeof(tuple_data);	tuple.TupleOffset     = 0;	CS_CHECK(GetFirstTuple, handle, &tuple);	CS_CHECK(GetTupleData,	handle, &tuple);	CS_CHECK(ParseTuple,	handle, &tuple, &parse);	link->conf.ConfigBase = parse.config.base;	link->conf.Present    = parse.config.rmask[0];	/* Configure card */	driver_template.module = &__this_module;	link->state	      |= DEV_CONFIG;	/* Look up the current Vcc */	CS_CHECK(GetConfigurationInfo, handle, &conf);	link->conf.Vcc = conf.Vcc;	tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;	CS_CHECK(GetFirstTuple, handle, &tuple);	while (1) {		CFG_CHECK(GetTupleData, handle, &tuple);		CFG_CHECK(ParseTuple,	handle, &tuple, &parse);		link->conf.ConfigIndex = parse.cftable_entry.index;		link->io.BasePort1     = parse.cftable_entry.io.win[0].base;		i = CardServices(RequestIO, handle, &link->io);		if (i == CS_SUCCESS) {			break;		}	next_entry:		DEBUG(0, __FUNCTION__ " next\n");		CS_CHECK(GetNextTuple, handle, &tuple);	}	CS_CHECK(RequestIRQ,	       handle, &link->irq);	CS_CHECK(RequestConfiguration, handle, &link->conf);	/* A bad hack... */	release_region(link->io.BasePort1, link->io.NumPorts1);	/* Set port and IRQ */	data->BaseAddress = link->io.BasePort1;	data->NumAddress  = link->io.NumPorts1;	data->IrqNumber   = link->irq.AssignedIRQ;	DEBUG(0, __FUNCTION__ " I/O[0x%x+0x%x] IRQ %d\n",	      data->BaseAddress, data->NumAddress, data->IrqNumber);	if(nsphw_init(data) == FALSE) {		goto cs_failed;	}	scsi_register_module(MODULE_SCSI_HA, &driver_template);	DEBUG(0, "GET_SCSI_INFO\n");	tail = &link->dev;	info->ndev = 0;	for (host = scsi_hostlist; host != NULL; host = host->next) {		if (host->hostt == &driver_template) {			for (dev = host->host_queue; dev != NULL; dev = dev->next) {				u_long arg[2], id;				kernel_scsi_ioctl(dev, SCSI_IOCTL_GET_IDLUN, arg);				id = (arg[0]&0x0f) + ((arg[0]>>4)&0xf0) +					((arg[0]>>8)&0xf00) + ((arg[0]>>12)&0xf000);				node = &info->node[info->ndev];				node->minor = 0;				switch (dev->type) {				case TYPE_TAPE:					node->major = SCSI_TAPE_MAJOR;					sprintf(node->dev_name, "st#%04lx", id);					break;				case TYPE_DISK:				case TYPE_MOD:					node->major = SCSI_DISK0_MAJOR;					sprintf(node->dev_name, "sd#%04lx", id);					break;				case TYPE_ROM:				case TYPE_WORM:					node->major = SCSI_CDROM_MAJOR;					sprintf(node->dev_name, "sr#%04lx", id);					break;				default:					node->major = SCSI_GENERIC_MAJOR;					sprintf(node->dev_name, "sg#%04lx", id);					break;				}				*tail = node; tail = &node->next;				info->ndev++;				info->host = dev->host;			}		}	}	*tail = NULL;	if (info->ndev == 0) {		printk(KERN_INFO "nsp_cs: no SCSI devices found\n");	}	/* Finally, report what we've done */	printk(KERN_INFO "nsp_cs: index 0x%02x: Vcc %d.%d",	       link->conf.ConfigIndex,	       link->conf.Vcc/10, link->conf.Vcc%10);	if (link->conf.Vpp1) {		printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);	}	if (link->conf.Attributes & CONF_ENABLE_IRQ) {		printk(", irq %d", link->irq.AssignedIRQ);	}	if (link->io.NumPorts1) {		printk(", io 0x%04x-0x%04x", link->io.BasePort1,		       link->io.BasePort1+link->io.NumPorts1-1);	}	printk("\n");	link->state &= ~DEV_CONFIG_PENDING;	return;cs_failed:	cs_error(link->handle, last_fn, last_ret);	nsp_cs_release((u_long)link);	return;} /* nsp_cs_config */#undef CS_CHECK#undef CFG_CHECK/*======================================================================    After a card is removed, nsp_cs_release() will unregister the net    device, and release the PCMCIA configuration.  If the device is    still open, this will be postponed until it is closed.======================================================================*/static void nsp_cs_release(u_long arg){	dev_link_t *link = (dev_link_t *)arg;	DEBUG(0, __FUNCTION__ "(0x%p)\n", link);	/*	 * If the device is currently in use, we won't release until it	 * is actually closed.	 */	if (link->open) {		DEBUG(1, "nsp_cs: release postponed, '%s' still open\n",		      link->dev->dev_name);		link->state |= DEV_STALE_CONFIG;		return;	}	/* Unlink the device chain */	scsi_unregister_module(MODULE_SCSI_HA, &driver_template);	link->dev = NULL;	if (link->win) {		CardServices(ReleaseWindow, link->win);	}	CardServices(ReleaseConfiguration,  link->handle);	if (link->io.NumPorts1) {		CardServices(ReleaseIO,     link->handle, &link->io);	}	if (link->irq.AssignedIRQ) {		CardServices(ReleaseIRQ,    link->handle, &link->irq);	}	link->state &= ~DEV_CONFIG;	if (link->state & DEV_STALE_LINK) {		nsp_cs_detach(link);	}} /* nsp_cs_release *//*======================================================================    The card status event handler.  Mostly, this schedules other    stuff to run after an event is received.  A CARD_REMOVAL event    also sets some flags to discourage the net drivers from trying    to talk to the card any more.    When a CARD_REMOVAL event is received, we immediately set a flag    to block future accesses to this device.  All the functions that    actually access the device should check this flag to make sure    the card is still present.    ======================================================================*/static int nsp_cs_event(event_t		    event,		     int		    priority,		     event_callback_args_t *args){	dev_link_t  *link = args->client_data;	scsi_info_t *info = link->priv;	DEBUG(1, __FUNCTION__ "(0x%06x)\n", event);	switch (event) {	case CS_EVENT_CARD_REMOVAL:		DEBUG(0, " event: remove\n");		link->state &= ~DEV_PRESENT;		if (link->state & DEV_CONFIG) {			((scsi_info_t *)link->priv)->stop = 1;			mod_timer(&link->release, jiffies + HZ/20);		}		break;	case CS_EVENT_CARD_INSERTION:		DEBUG(0, " event: insert\n");		link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;		info->bus    =  args->bus;		nsp_cs_config(link);		break;	case CS_EVENT_PM_SUSPEND:		link->state |= DEV_SUSPEND;		/* Fall through... */	case CS_EVENT_RESET_PHYSICAL:		/* Mark the device as stopped, to block IO until later */		info->stop = 1;		if (link->state & DEV_CONFIG) {			CardServices(ReleaseConfiguration, link->handle);		}		break;	case CS_EVENT_PM_RESUME:		link->state &= ~DEV_SUSPEND;		/* Fall through... */	case CS_EVENT_CARD_RESET:		DEBUG(0, " event: reset\n");		if (link->state & DEV_CONFIG) {			Scsi_Cmnd tmp;			CardServices(RequestConfiguration, link->handle, &link->conf);			tmp.host = info->host;			nsp_eh_host_reset(&tmp);		}		info->stop = 0;		break;	default:		DEBUG(0, " event: unknown\n");		break;	}	DEBUG(0, __FUNCTION__ " end\n");	return 0;} /* nsp_cs_event *//*======================================================================* *	module entry point *====================================================================*/static int __init nsp_cs_init(void){	servinfo_t serv;	DEBUG(0, __FUNCTION__ "() in\n");	DEBUG(0, "%s\n", version);	CardServices(GetCardServicesInfo, &serv);	if (serv.Revision != CS_RELEASE_CODE) {		printk(KERN_DEBUG "nsp_cs: Card Services release "		       "does not match!\n");		return -1;	}	register_pcmcia_driver(&dev_info, &nsp_cs_attach, &nsp_cs_detach);	DEBUG(0, __FUNCTION__ "() out\n");	return 0;}static void __exit nsp_cs_cleanup(void){	DEBUG(0, __FUNCTION__ "() unloading\n");	unregister_pcmcia_driver(&dev_info);	while (dev_list != NULL) {		if (dev_list->state & DEV_CONFIG) {			nsp_cs_release((u_long)dev_list);		}		nsp_cs_detach(dev_list);	}}module_init(nsp_cs_init);module_exit(nsp_cs_cleanup);/* * * *//* end */

⌨️ 快捷键说明

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