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

📄 spectrum_cs.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 3 页
字号:
		 */		if (pdr_len(pdr) < 2)			return NULL;		/* If the record ID matches, we are done */		if (pdr_id(pdr) == record_id)			return pdr;		pdr = (struct pdr *) pdr->next;	}	return NULL;}/* Process one Plug Data Item - find corresponding PDR and plug it */static intspectrum_plug_pdi(hermes_t *hw, struct pdr *first_pdr, struct pdi *pdi){	struct pdr *pdr;	/* Find the PDI corresponding to this PDR */	pdr = spectrum_find_pdr(first_pdr, pdi_id(pdi));	/* No match is found, safe to ignore */	if (!pdr)		return 0;	/* Lengths of the data in PDI and PDR must match */	if (pdi_len(pdi) != pdr_len(pdr))		return -EINVAL;	/* do the actual plugging */	spectrum_aux_setaddr(hw, pdr_addr(pdr));	hermes_write_words(hw, HERMES_AUXDATA, pdi->data,			   pdi_len(pdi) / 2);	return 0;}/* Read PDA from the adapter */static intspectrum_read_pda(hermes_t *hw, u16 *pda, int pda_len){	int ret;	int pda_size;	/* Issue command to read EEPROM */	ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL);	if (ret)		return ret;	/* Open auxiliary port */	ret = spectrum_aux_open(hw);	if (ret)		return ret;	/* read PDA from EEPROM */	spectrum_aux_setaddr(hw, PDA_ADDR);	hermes_read_words(hw, HERMES_AUXDATA, pda, pda_len / 2);	/* Check PDA length */	pda_size = le16_to_cpu(pda[0]);	if (pda_size > pda_len)		return -EINVAL;	return 0;}/* Parse PDA and write the records into the adapter */static intspectrum_apply_pda(hermes_t *hw, const struct dblock *first_block,		   u16 *pda){	int ret;	struct pdi *pdi;	struct pdr *first_pdr;	const struct dblock *blk = first_block;	/* Skip all blocks to locate Plug Data References */	while (dblock_addr(blk) != BLOCK_END)		blk = (struct dblock *) &blk->data[dblock_len(blk)];	first_pdr = (struct pdr *) blk;	/* Go through every PDI and plug them into the adapter */	pdi = (struct pdi *) (pda + 2);	while (pdi_id(pdi) != PDI_END) {		ret = spectrum_plug_pdi(hw, first_pdr, pdi);		if (ret)			return ret;		/* Increment to the next PDI */		pdi = (struct pdi *) &pdi->data[pdi_len(pdi)];	}	return 0;}/* Load firmware blocks into the adapter */static intspectrum_load_blocks(hermes_t *hw, const struct dblock *first_block){	const struct dblock *blk;	u32 blkaddr;	u32 blklen;	blk = first_block;	blkaddr = dblock_addr(blk);	blklen = dblock_len(blk);	while (dblock_addr(blk) != BLOCK_END) {		spectrum_aux_setaddr(hw, blkaddr);		hermes_write_words(hw, HERMES_AUXDATA, blk->data,				   blklen / 2);		blk = (struct dblock *) &blk->data[blklen];		blkaddr = dblock_addr(blk);		blklen = dblock_len(blk);	}	return 0;}/* * Process a firmware image - stop the card, load the firmware, reset * the card and make sure it responds.  For the secondary firmware take * care of the PDA - read it and then write it on top of the firmware. */static intspectrum_dl_image(hermes_t *hw, dev_link_t *link,		  const unsigned char *image){	int ret;	const unsigned char *ptr;	const struct dblock *first_block;	/* Plug Data Area (PDA) */	u16 pda[PDA_WORDS];	/* Binary block begins after the 0x1A marker */	ptr = image;	while (*ptr++ != TEXT_END);	first_block = (const struct dblock *) ptr;	/* Read the PDA */	if (image != primsym) {		ret = spectrum_read_pda(hw, pda, sizeof(pda));		if (ret)			return ret;	}	/* Stop the firmware, so that it can be safely rewritten */	ret = spectrum_reset(link, 1);	if (ret)		return ret;	/* Program the adapter with new firmware */	ret = spectrum_load_blocks(hw, first_block);	if (ret)		return ret;	/* Write the PDA to the adapter */	if (image != primsym) {		ret = spectrum_apply_pda(hw, first_block, pda);		if (ret)			return ret;	}	/* Run the firmware */	ret = spectrum_reset(link, 0);	if (ret)		return ret;	/* Reset hermes chip and make sure it responds */	ret = hermes_init(hw);	/* hermes_reset() should return 0 with the secondary firmware */	if (image != primsym && ret != 0)		return -ENODEV;	/* And this should work with any firmware */	if (!hermes_present(hw))		return -ENODEV;	return 0;}/* * Download the firmware into the card, this also does a PCMCIA soft * reset on the card, to make sure it's in a sane state. */static intspectrum_dl_firmware(hermes_t *hw, dev_link_t *link){	int ret;	client_handle_t handle = link->handle;#ifndef SPECTRUM_FW_INCLUDED	const struct firmware *fw_entry;	if (request_firmware(&fw_entry, primary_fw_name,			     &handle_to_dev(handle)) == 0) {		primsym = fw_entry->data;	} else {		printk(KERN_ERR PFX "Cannot find firmware: %s\n",		       primary_fw_name);		return -ENOENT;	}	if (request_firmware(&fw_entry, secondary_fw_name,			     &handle_to_dev(handle)) == 0) {		secsym = fw_entry->data;	} else {		printk(KERN_ERR PFX "Cannot find firmware: %s\n",		       secondary_fw_name);		return -ENOENT;	}#endif	/* Load primary firmware */	ret = spectrum_dl_image(hw, link, primsym);	if (ret) {		printk(KERN_ERR PFX "Primary firmware download failed\n");		return ret;	}	/* Load secondary firmware */	ret = spectrum_dl_image(hw, link, secsym);	if (ret) {		printk(KERN_ERR PFX "Secondary firmware download failed\n");	}	return ret;}/********************************************************************//* Device methods     						    *//********************************************************************/static intspectrum_cs_hard_reset(struct orinoco_private *priv){	struct orinoco_pccard *card = priv->card;	dev_link_t *link = &card->link;	int err;	if (!hermes_present(&priv->hw)) {		/* The firmware needs to be reloaded */		if (spectrum_dl_firmware(&priv->hw, &card->link) != 0) {			printk(KERN_ERR PFX "Firmware download failed\n");			err = -ENODEV;		}	} else {		/* Soft reset using COR and HCR */		spectrum_reset(link, 0);	}	return 0;}/********************************************************************//* PCMCIA stuff     						    *//********************************************************************//* * This 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 *spectrum_cs_attach(void){	struct net_device *dev;	struct orinoco_private *priv;	struct orinoco_pccard *card;	dev_link_t *link;	client_reg_t client_reg;	int ret;	dev = alloc_orinocodev(sizeof(*card), spectrum_cs_hard_reset);	if (! dev)		return NULL;	priv = netdev_priv(dev);	card = priv->card;	/* Link both structures together */	link = &card->link;	link->priv = dev;	/* Interrupt setup */	link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;	link->irq.IRQInfo1 = IRQ_LEVEL_ID;	link->irq.Handler = orinoco_interrupt;	link->irq.Instance = dev; 	/* General socket configuration defaults can go here.  In this	 * client, we assume very little, and rely on the CIS for	 * almost everything.  In most clients, many details (i.e.,	 * number, sizes, and attributes of IO windows) are fixed by	 * the nature of the device, and can be hard-wired here. */	link->conf.Attributes = 0;	link->conf.IntType = INT_MEMORY_AND_IO;	/* Register with Card Services */	/* FIXME: need a lock? */	link->next = dev_list;	dev_list = link;	client_reg.dev_info = &dev_info;	client_reg.Version = 0x0210; /* FIXME: what does this mean? */	client_reg.event_callback_args.client_data = link;	ret = pcmcia_register_client(&link->handle, &client_reg);	if (ret != CS_SUCCESS) {		cs_error(link->handle, RegisterClient, ret);		spectrum_cs_detach(link);		return NULL;	}	return link;}				/* spectrum_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 spectrum_cs_detach(dev_link_t *link){	dev_link_t **linkp;	struct net_device *dev = link->priv;	/* Locate device structure */	for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)		if (*linkp == link)			break;	BUG_ON(*linkp == NULL);	if (link->state & DEV_CONFIG)		spectrum_cs_release(link);	/* Break the link with Card Services */	if (link->handle)		pcmcia_deregister_client(link->handle);	/* Unlink device structure, and free it */	*linkp = link->next;	DEBUG(0, PFX "detach: link=%p link->dev=%p\n", link, link->dev);	if (link->dev) {		DEBUG(0, PFX "About to unregister net device %p\n",		      dev);		unregister_netdev(dev);	}	free_orinocodev(dev);}				/* spectrum_cs_detach *//* * spectrum_cs_config() is scheduled to run after a CARD_INSERTION * event is received, to configure the PCMCIA socket, and to make the * device available to the system. */static voidspectrum_cs_config(dev_link_t *link){

⌨️ 快捷键说明

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