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

📄 ipw2100.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
                    3. hold ARC (don't ask me why...)                    4. load Dino ucode and reset/clock init again                    5. zero-out shared mem                    6. download f/w *******************************************************************/static int ipw2100_download_firmware(struct ipw2100_priv *priv){	u32 address;	int err;#ifndef CONFIG_PM	/* Fetch the firmware and microcode */	struct ipw2100_fw ipw2100_firmware;#endif	if (priv->fatal_error) {		IPW_DEBUG_ERROR("%s: ipw2100_download_firmware called after "				"fatal error %d.  Interface must be brought down.\n",				priv->net_dev->name, priv->fatal_error);		return -EINVAL;	}#ifdef CONFIG_PM	if (!ipw2100_firmware.version) {		err = ipw2100_get_firmware(priv, &ipw2100_firmware);		if (err) {			IPW_DEBUG_ERROR("%s: ipw2100_get_firmware failed: %d\n",					priv->net_dev->name, err);			priv->fatal_error = IPW2100_ERR_FW_LOAD;			goto fail;		}	}#else	err = ipw2100_get_firmware(priv, &ipw2100_firmware);	if (err) {		IPW_DEBUG_ERROR("%s: ipw2100_get_firmware failed: %d\n",				priv->net_dev->name, err);		priv->fatal_error = IPW2100_ERR_FW_LOAD;		goto fail;	}#endif	priv->firmware_version = ipw2100_firmware.version;	/* s/w reset and clock stabilization */	err = sw_reset_and_clock(priv);	if (err) {		IPW_DEBUG_ERROR("%s: sw_reset_and_clock failed: %d\n",				priv->net_dev->name, err);		goto fail;	}	err = ipw2100_verify(priv);	if (err) {		IPW_DEBUG_ERROR("%s: ipw2100_verify failed: %d\n",				priv->net_dev->name, err);		goto fail;	}	/* Hold ARC */	write_nic_dword(priv->net_dev,			IPW_INTERNAL_REGISTER_HALT_AND_RESET, 0x80000000);	/* allow ARC to run */	write_register(priv->net_dev, IPW_REG_RESET_REG, 0);	/* load microcode */	err = ipw2100_ucode_download(priv, &ipw2100_firmware);	if (err) {		printk(KERN_ERR DRV_NAME ": %s: Error loading microcode: %d\n",		       priv->net_dev->name, err);		goto fail;	}	/* release ARC */	write_nic_dword(priv->net_dev,			IPW_INTERNAL_REGISTER_HALT_AND_RESET, 0x00000000);	/* s/w reset and clock stabilization (again!!!) */	err = sw_reset_and_clock(priv);	if (err) {		printk(KERN_ERR DRV_NAME		       ": %s: sw_reset_and_clock failed: %d\n",		       priv->net_dev->name, err);		goto fail;	}	/* load f/w */	err = ipw2100_fw_download(priv, &ipw2100_firmware);	if (err) {		IPW_DEBUG_ERROR("%s: Error loading firmware: %d\n",				priv->net_dev->name, err);		goto fail;	}#ifndef CONFIG_PM	/*	 * When the .resume method of the driver is called, the other	 * part of the system, i.e. the ide driver could still stay in	 * the suspend stage. This prevents us from loading the firmware	 * from the disk.  --YZ	 */	/* free any storage allocated for firmware image */	ipw2100_release_firmware(priv, &ipw2100_firmware);#endif	/* zero out Domain 1 area indirectly (Si requirement) */	for (address = IPW_HOST_FW_SHARED_AREA0;	     address < IPW_HOST_FW_SHARED_AREA0_END; address += 4)		write_nic_dword(priv->net_dev, address, 0);	for (address = IPW_HOST_FW_SHARED_AREA1;	     address < IPW_HOST_FW_SHARED_AREA1_END; address += 4)		write_nic_dword(priv->net_dev, address, 0);	for (address = IPW_HOST_FW_SHARED_AREA2;	     address < IPW_HOST_FW_SHARED_AREA2_END; address += 4)		write_nic_dword(priv->net_dev, address, 0);	for (address = IPW_HOST_FW_SHARED_AREA3;	     address < IPW_HOST_FW_SHARED_AREA3_END; address += 4)		write_nic_dword(priv->net_dev, address, 0);	for (address = IPW_HOST_FW_INTERRUPT_AREA;	     address < IPW_HOST_FW_INTERRUPT_AREA_END; address += 4)		write_nic_dword(priv->net_dev, address, 0);	return 0;      fail:	ipw2100_release_firmware(priv, &ipw2100_firmware);	return err;}static inline void ipw2100_enable_interrupts(struct ipw2100_priv *priv){	if (priv->status & STATUS_INT_ENABLED)		return;	priv->status |= STATUS_INT_ENABLED;	write_register(priv->net_dev, IPW_REG_INTA_MASK, IPW_INTERRUPT_MASK);}static inline void ipw2100_disable_interrupts(struct ipw2100_priv *priv){	if (!(priv->status & STATUS_INT_ENABLED))		return;	priv->status &= ~STATUS_INT_ENABLED;	write_register(priv->net_dev, IPW_REG_INTA_MASK, 0x0);}static void ipw2100_initialize_ordinals(struct ipw2100_priv *priv){	struct ipw2100_ordinals *ord = &priv->ordinals;	IPW_DEBUG_INFO("enter\n");	read_register(priv->net_dev, IPW_MEM_HOST_SHARED_ORDINALS_TABLE_1,		      &ord->table1_addr);	read_register(priv->net_dev, IPW_MEM_HOST_SHARED_ORDINALS_TABLE_2,		      &ord->table2_addr);	read_nic_dword(priv->net_dev, ord->table1_addr, &ord->table1_size);	read_nic_dword(priv->net_dev, ord->table2_addr, &ord->table2_size);	ord->table2_size &= 0x0000FFFF;	IPW_DEBUG_INFO("table 1 size: %d\n", ord->table1_size);	IPW_DEBUG_INFO("table 2 size: %d\n", ord->table2_size);	IPW_DEBUG_INFO("exit\n");}static inline void ipw2100_hw_set_gpio(struct ipw2100_priv *priv){	u32 reg = 0;	/*	 * Set GPIO 3 writable by FW; GPIO 1 writable	 * by driver and enable clock	 */	reg = (IPW_BIT_GPIO_GPIO3_MASK | IPW_BIT_GPIO_GPIO1_ENABLE |	       IPW_BIT_GPIO_LED_OFF);	write_register(priv->net_dev, IPW_REG_GPIO, reg);}static inline int rf_kill_active(struct ipw2100_priv *priv){#define MAX_RF_KILL_CHECKS 5#define RF_KILL_CHECK_DELAY 40	unsigned short value = 0;	u32 reg = 0;	int i;	if (!(priv->hw_features & HW_FEATURE_RFKILL)) {		priv->status &= ~STATUS_RF_KILL_HW;		return 0;	}	for (i = 0; i < MAX_RF_KILL_CHECKS; i++) {		udelay(RF_KILL_CHECK_DELAY);		read_register(priv->net_dev, IPW_REG_GPIO, &reg);		value = (value << 1) | ((reg & IPW_BIT_GPIO_RF_KILL) ? 0 : 1);	}	if (value == 0)		priv->status |= STATUS_RF_KILL_HW;	else		priv->status &= ~STATUS_RF_KILL_HW;	return (value == 0);}static int ipw2100_get_hw_features(struct ipw2100_priv *priv){	u32 addr, len;	u32 val;	/*	 * EEPROM_SRAM_DB_START_ADDRESS using ordinal in ordinal table 1	 */	len = sizeof(addr);	if (ipw2100_get_ordinal	    (priv, IPW_ORD_EEPROM_SRAM_DB_BLOCK_START_ADDRESS, &addr, &len)) {		IPW_DEBUG_INFO("failed querying ordinals at line %d\n",			       __LINE__);		return -EIO;	}	IPW_DEBUG_INFO("EEPROM address: %08X\n", addr);	/*	 * EEPROM version is the byte at offset 0xfd in firmware	 * We read 4 bytes, then shift out the byte we actually want */	read_nic_dword(priv->net_dev, addr + 0xFC, &val);	priv->eeprom_version = (val >> 24) & 0xFF;	IPW_DEBUG_INFO("EEPROM version: %d\n", priv->eeprom_version);	/*	 *  HW RF Kill enable is bit 0 in byte at offset 0x21 in firmware	 *	 *  notice that the EEPROM bit is reverse polarity, i.e.	 *     bit = 0  signifies HW RF kill switch is supported	 *     bit = 1  signifies HW RF kill switch is NOT supported	 */	read_nic_dword(priv->net_dev, addr + 0x20, &val);	if (!((val >> 24) & 0x01))		priv->hw_features |= HW_FEATURE_RFKILL;	IPW_DEBUG_INFO("HW RF Kill: %ssupported.\n",		       (priv->hw_features & HW_FEATURE_RFKILL) ? "" : "not ");	return 0;}/* * Start firmware execution after power on and intialization * The sequence is: *  1. Release ARC *  2. Wait for f/w initialization completes; */static int ipw2100_start_adapter(struct ipw2100_priv *priv){	int i;	u32 inta, inta_mask, gpio;	IPW_DEBUG_INFO("enter\n");	if (priv->status & STATUS_RUNNING)		return 0;	/*	 * Initialize the hw - drive adapter to DO state by setting	 * init_done bit. Wait for clk_ready bit and Download	 * fw & dino ucode	 */	if (ipw2100_download_firmware(priv)) {		printk(KERN_ERR DRV_NAME		       ": %s: Failed to power on the adapter.\n",		       priv->net_dev->name);		return -EIO;	}	/* Clear the Tx, Rx and Msg queues and the r/w indexes	 * in the firmware RBD and TBD ring queue */	ipw2100_queues_initialize(priv);	ipw2100_hw_set_gpio(priv);	/* TODO -- Look at disabling interrupts here to make sure none	 * get fired during FW initialization */	/* Release ARC - clear reset bit */	write_register(priv->net_dev, IPW_REG_RESET_REG, 0);	/* wait for f/w intialization complete */	IPW_DEBUG_FW("Waiting for f/w initialization to complete...\n");	i = 5000;	do {		schedule_timeout_uninterruptible(msecs_to_jiffies(40));		/* Todo... wait for sync command ... */		read_register(priv->net_dev, IPW_REG_INTA, &inta);		/* check "init done" bit */		if (inta & IPW2100_INTA_FW_INIT_DONE) {			/* reset "init done" bit */			write_register(priv->net_dev, IPW_REG_INTA,				       IPW2100_INTA_FW_INIT_DONE);			break;		}		/* check error conditions : we check these after the firmware		 * check so that if there is an error, the interrupt handler		 * will see it and the adapter will be reset */		if (inta &		    (IPW2100_INTA_FATAL_ERROR | IPW2100_INTA_PARITY_ERROR)) {			/* clear error conditions */			write_register(priv->net_dev, IPW_REG_INTA,				       IPW2100_INTA_FATAL_ERROR |				       IPW2100_INTA_PARITY_ERROR);		}	} while (i--);	/* Clear out any pending INTAs since we aren't supposed to have	 * interrupts enabled at this point... */	read_register(priv->net_dev, IPW_REG_INTA, &inta);	read_register(priv->net_dev, IPW_REG_INTA_MASK, &inta_mask);	inta &= IPW_INTERRUPT_MASK;	/* Clear out any pending interrupts */	if (inta & inta_mask)		write_register(priv->net_dev, IPW_REG_INTA, inta);	IPW_DEBUG_FW("f/w initialization complete: %s\n",		     i ? "SUCCESS" : "FAILED");	if (!i) {		printk(KERN_WARNING DRV_NAME		       ": %s: Firmware did not initialize.\n",		       priv->net_dev->name);		return -EIO;	}	/* allow firmware to write to GPIO1 & GPIO3 */	read_register(priv->net_dev, IPW_REG_GPIO, &gpio);	gpio |= (IPW_BIT_GPIO_GPIO1_MASK | IPW_BIT_GPIO_GPIO3_MASK);	write_register(priv->net_dev, IPW_REG_GPIO, gpio);	/* Ready to receive commands */	priv->status |= STATUS_RUNNING;	/* The adapter has been reset; we are not associated */	priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED);	IPW_DEBUG_INFO("exit\n");	return 0;}static inline void ipw2100_reset_fatalerror(struct ipw2100_priv *priv){	if (!priv->fatal_error)		return;	priv->fatal_errors[priv->fatal_index++] = priv->fatal_error;	priv->fatal_index %= IPW2100_ERROR_QUEUE;	priv->fatal_error = 0;}/* NOTE: Our interrupt is disabled when this method is called */static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv){	u32 reg;	int i;	IPW_DEBUG_INFO("Power cycling the hardware.\n");	ipw2100_hw_set_gpio(priv);	/* Step 1. Stop Master Assert */	write_register(priv->net_dev, IPW_REG_RESET_REG,		       IPW_AUX_HOST_RESET_REG_STOP_MASTER);	/* Step 2. Wait for stop Master Assert	 *         (not more then 50us, otherwise ret error */	i = 5;	do {		udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY);		read_register(priv->net_dev, IPW_REG_RESET_REG, &reg);		if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED)			break;	} while (i--);	priv->status &= ~STATUS_RESET_PENDING;	if (!i) {		IPW_DEBUG_INFO		    ("exit - waited too long for master assert stop\n");		return -EIO;	}	write_register(priv->net_dev, IPW_REG_RESET_REG,		       IPW_AUX_HOST_RESET_REG_SW_RESET);	/* Reset any fatal_error conditions */	ipw2100_reset_fatalerror(priv);	/* At this point, the adapter is now stopped and disabled */	priv->status &= ~(STATUS_RUNNING | STATUS_ASSOCIATING |			  STATUS_ASSOCIATED | STATUS_ENABLED);	return 0;}/* * Send the CARD_DISABLE_PHY_OFF comamnd to the card to disable it * * After disabling, if the card was associated, a STATUS_ASSN_LOST will be sent. * * STATUS_CARD_DISABLE_NOTIFICATION will be sent regardless of * if STATUS_ASSN_LOST is sent. */static int ipw2100_hw_phy_off(struct ipw2100_priv *priv){#define HW_PHY_OFF_LOOP_DELAY (HZ / 5000)	struct host_command cmd = {		.host_command = CARD_DISABLE_PHY_OFF,		.host_command_sequence = 0,		.host_command_length = 0,	};	int err, i;	u32 val1, val2;	IPW_DEBUG_HC("CARD_DISABLE_PHY_OFF\n");	/* Turn off the radio */	err = ipw2100_hw_send_command(priv, &cmd);	if (err)		return err;	for (i = 0; i < 2500; i++) {		read_nic_dword(priv->net_dev, IPW2100_CONTROL_REG, &val1);		read_nic_dword(priv->net_dev, IPW2100_COMMAND, &val2);		if ((val1 & IPW2100_CONTROL_PHY_OFF) &&		    (val2 & IPW2100_COMMAND_PHY_OFF))			return 0;		schedule_timeout_uninterruptible(HW_PHY_OFF_LOOP_DELAY);	}	return -EIO;}static int ipw2100_enable_adapter(struct ipw2100_priv *priv){	struct host_command cmd = {		.host_command = HOST_COMPLETE,		.host_command_sequence = 0,		.host_command_length = 0	};	int err = 0;	IPW_DEBUG_HC("HOST_COMPLETE\n");	if (priv->status & STATUS_ENABLED)		return 0;	down(&priv->adapter_sem);	if (rf_kill_active(priv)) {		IPW_DEBUG_HC("Command aborted due to RF kill active.\n");		goto fail_up;	}	err = ipw2100_hw_send_command(priv, &cmd);	if (err) {		IPW_DEBUG_INFO("Failed to send HOST_COMPLETE command\n");		goto fail_up;

⌨️ 快捷键说明

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