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

📄 main.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	spin_unlock(&dev->wl->irq_lock);	return ret;}static void b43legacy_release_firmware(struct b43legacy_wldev *dev){	release_firmware(dev->fw.ucode);	dev->fw.ucode = NULL;	release_firmware(dev->fw.pcm);	dev->fw.pcm = NULL;	release_firmware(dev->fw.initvals);	dev->fw.initvals = NULL;	release_firmware(dev->fw.initvals_band);	dev->fw.initvals_band = NULL;}static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl){	b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/"		     "Drivers/b43#devicefirmware "		     "and download the correct firmware (version 3).\n");}static int do_request_fw(struct b43legacy_wldev *dev,			 const char *name,			 const struct firmware **fw){	char path[sizeof(modparam_fwpostfix) + 32];	struct b43legacy_fw_header *hdr;	u32 size;	int err;	if (!name)		return 0;	snprintf(path, ARRAY_SIZE(path),		 "b43legacy%s/%s.fw",		 modparam_fwpostfix, name);	err = request_firmware(fw, path, dev->dev->dev);	if (err) {		b43legacyerr(dev->wl, "Firmware file \"%s\" not found "		       "or load failed.\n", path);		return err;	}	if ((*fw)->size < sizeof(struct b43legacy_fw_header))		goto err_format;	hdr = (struct b43legacy_fw_header *)((*fw)->data);	switch (hdr->type) {	case B43legacy_FW_TYPE_UCODE:	case B43legacy_FW_TYPE_PCM:		size = be32_to_cpu(hdr->size);		if (size != (*fw)->size - sizeof(struct b43legacy_fw_header))			goto err_format;		/* fallthrough */	case B43legacy_FW_TYPE_IV:		if (hdr->ver != 1)			goto err_format;		break;	default:		goto err_format;	}	return err;err_format:	b43legacyerr(dev->wl, "Firmware file \"%s\" format error.\n", path);	return -EPROTO;}static int b43legacy_request_firmware(struct b43legacy_wldev *dev){	struct b43legacy_firmware *fw = &dev->fw;	const u8 rev = dev->dev->id.revision;	const char *filename;	u32 tmshigh;	int err;	tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH);	if (!fw->ucode) {		if (rev == 2)			filename = "ucode2";		else if (rev == 4)			filename = "ucode4";		else			filename = "ucode5";		err = do_request_fw(dev, filename, &fw->ucode);		if (err)			goto err_load;	}	if (!fw->pcm) {		if (rev < 5)			filename = "pcm4";		else			filename = "pcm5";		err = do_request_fw(dev, filename, &fw->pcm);		if (err)			goto err_load;	}	if (!fw->initvals) {		switch (dev->phy.type) {		case B43legacy_PHYTYPE_G:			if ((rev >= 5) && (rev <= 10))				filename = "b0g0initvals5";			else if (rev == 2 || rev == 4)				filename = "b0g0initvals2";			else				goto err_no_initvals;			break;		default:			goto err_no_initvals;		}		err = do_request_fw(dev, filename, &fw->initvals);		if (err)			goto err_load;	}	if (!fw->initvals_band) {		switch (dev->phy.type) {		case B43legacy_PHYTYPE_G:			if ((rev >= 5) && (rev <= 10))				filename = "b0g0bsinitvals5";			else if (rev >= 11)				filename = NULL;			else if (rev == 2 || rev == 4)				filename = NULL;			else				goto err_no_initvals;			break;		default:			goto err_no_initvals;		}		err = do_request_fw(dev, filename, &fw->initvals_band);		if (err)			goto err_load;	}	return 0;err_load:	b43legacy_print_fw_helptext(dev->wl);	goto error;err_no_initvals:	err = -ENODEV;	b43legacyerr(dev->wl, "No Initial Values firmware file for PHY %u, "	       "core rev %u\n", dev->phy.type, rev);	goto error;error:	b43legacy_release_firmware(dev);	return err;}static int b43legacy_upload_microcode(struct b43legacy_wldev *dev){	const size_t hdr_len = sizeof(struct b43legacy_fw_header);	const __be32 *data;	unsigned int i;	unsigned int len;	u16 fwrev;	u16 fwpatch;	u16 fwdate;	u16 fwtime;	u32 tmp;	int err = 0;	/* Upload Microcode. */	data = (__be32 *) (dev->fw.ucode->data + hdr_len);	len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32);	b43legacy_shm_control_word(dev,				   B43legacy_SHM_UCODE |				   B43legacy_SHM_AUTOINC_W,				   0x0000);	for (i = 0; i < len; i++) {		b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA,				    be32_to_cpu(data[i]));		udelay(10);	}	if (dev->fw.pcm) {		/* Upload PCM data. */		data = (__be32 *) (dev->fw.pcm->data + hdr_len);		len = (dev->fw.pcm->size - hdr_len) / sizeof(__be32);		b43legacy_shm_control_word(dev, B43legacy_SHM_HW, 0x01EA);		b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, 0x00004000);		/* No need for autoinc bit in SHM_HW */		b43legacy_shm_control_word(dev, B43legacy_SHM_HW, 0x01EB);		for (i = 0; i < len; i++) {			b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA,					  be32_to_cpu(data[i]));			udelay(10);		}	}	b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,			  B43legacy_IRQ_ALL);	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0x00020402);	/* Wait for the microcode to load and respond */	i = 0;	while (1) {		tmp = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);		if (tmp == B43legacy_IRQ_MAC_SUSPENDED)			break;		i++;		if (i >= B43legacy_IRQWAIT_MAX_RETRIES) {			b43legacyerr(dev->wl, "Microcode not responding\n");			b43legacy_print_fw_helptext(dev->wl);			err = -ENODEV;			goto out;		}		udelay(10);	}	/* dummy read follows */	b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);	/* Get and check the revisions. */	fwrev = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,				     B43legacy_SHM_SH_UCODEREV);	fwpatch = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,				       B43legacy_SHM_SH_UCODEPATCH);	fwdate = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,				      B43legacy_SHM_SH_UCODEDATE);	fwtime = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED,				      B43legacy_SHM_SH_UCODETIME);	if (fwrev > 0x128) {		b43legacyerr(dev->wl, "YOU ARE TRYING TO LOAD V4 FIRMWARE."			     " Only firmware from binary drivers version 3.x"			     " is supported. You must change your firmware"			     " files.\n");		b43legacy_print_fw_helptext(dev->wl);		b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD, 0);		err = -EOPNOTSUPP;		goto out;	}	b43legacydbg(dev->wl, "Loading firmware version 0x%X, patch level %u "	       "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch,	       (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF,	       (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F);	dev->fw.rev = fwrev;	dev->fw.patch = fwpatch;out:	return err;}static int b43legacy_write_initvals(struct b43legacy_wldev *dev,				    const struct b43legacy_iv *ivals,				    size_t count,				    size_t array_size){	const struct b43legacy_iv *iv;	u16 offset;	size_t i;	bool bit32;	BUILD_BUG_ON(sizeof(struct b43legacy_iv) != 6);	iv = ivals;	for (i = 0; i < count; i++) {		if (array_size < sizeof(iv->offset_size))			goto err_format;		array_size -= sizeof(iv->offset_size);		offset = be16_to_cpu(iv->offset_size);		bit32 = !!(offset & B43legacy_IV_32BIT);		offset &= B43legacy_IV_OFFSET_MASK;		if (offset >= 0x1000)			goto err_format;		if (bit32) {			u32 value;			if (array_size < sizeof(iv->data.d32))				goto err_format;			array_size -= sizeof(iv->data.d32);			value = be32_to_cpu(get_unaligned(&iv->data.d32));			b43legacy_write32(dev, offset, value);			iv = (const struct b43legacy_iv *)((const uint8_t *)iv +							sizeof(__be16) +							sizeof(__be32));		} else {			u16 value;			if (array_size < sizeof(iv->data.d16))				goto err_format;			array_size -= sizeof(iv->data.d16);			value = be16_to_cpu(iv->data.d16);			b43legacy_write16(dev, offset, value);			iv = (const struct b43legacy_iv *)((const uint8_t *)iv +							sizeof(__be16) +							sizeof(__be16));		}	}	if (array_size)		goto err_format;	return 0;err_format:	b43legacyerr(dev->wl, "Initial Values Firmware file-format error.\n");	b43legacy_print_fw_helptext(dev->wl);	return -EPROTO;}static int b43legacy_upload_initvals(struct b43legacy_wldev *dev){	const size_t hdr_len = sizeof(struct b43legacy_fw_header);	const struct b43legacy_fw_header *hdr;	struct b43legacy_firmware *fw = &dev->fw;	const struct b43legacy_iv *ivals;	size_t count;	int err;	hdr = (const struct b43legacy_fw_header *)(fw->initvals->data);	ivals = (const struct b43legacy_iv *)(fw->initvals->data + hdr_len);	count = be32_to_cpu(hdr->size);	err = b43legacy_write_initvals(dev, ivals, count,				 fw->initvals->size - hdr_len);	if (err)		goto out;	if (fw->initvals_band) {		hdr = (const struct b43legacy_fw_header *)		      (fw->initvals_band->data);		ivals = (const struct b43legacy_iv *)(fw->initvals_band->data			+ hdr_len);		count = be32_to_cpu(hdr->size);		err = b43legacy_write_initvals(dev, ivals, count,					 fw->initvals_band->size - hdr_len);		if (err)			goto out;	}out:	return err;}/* Initialize the GPIOs * http://bcm-specs.sipsolutions.net/GPIO */static int b43legacy_gpio_init(struct b43legacy_wldev *dev){	struct ssb_bus *bus = dev->dev->bus;	struct ssb_device *gpiodev, *pcidev = NULL;	u32 mask;	u32 set;	b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,			  b43legacy_read32(dev,			  B43legacy_MMIO_STATUS_BITFIELD)			  & 0xFFFF3FFF);	b43legacy_leds_switch_all(dev, 0);	b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,			  b43legacy_read16(dev,			  B43legacy_MMIO_GPIO_MASK)			  | 0x000F);	mask = 0x0000001F;	set = 0x0000000F;	if (dev->dev->bus->chip_id == 0x4301) {		mask |= 0x0060;		set |= 0x0060;	}	if (dev->dev->bus->sprom.r1.boardflags_lo & B43legacy_BFL_PACTRL) {		b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK,				  b43legacy_read16(dev,				  B43legacy_MMIO_GPIO_MASK)				  | 0x0200);		mask |= 0x0200;		set |= 0x0200;	}	if (dev->dev->id.revision >= 2)		mask  |= 0x0010; /* FIXME: This is redundant. */#ifdef CONFIG_SSB_DRIVER_PCICORE	pcidev = bus->pcicore.dev;#endif	gpiodev = bus->chipco.dev ? : pcidev;	if (!gpiodev)		return 0;	ssb_write32(gpiodev, B43legacy_GPIO_CONTROL,		    (ssb_read32(gpiodev, B43legacy_GPIO_CONTROL)		     & mask) | set);	return 0;}/* Turn off all GPIO stuff. Call this on module unload, for example. */static void b43legacy_gpio_cleanup(struct b43legacy_wldev *dev){	struct ssb_bus *bus = dev->dev->bus;	struct ssb_device *gpiodev, *pcidev = NULL;#ifdef CONFIG_SSB_DRIVER_PCICORE	pcidev = bus->pcicore.dev;#endif	gpiodev = bus->chipco.dev ? : pcidev;	if (!gpiodev)		return;	ssb_write32(gpiodev, B43legacy_GPIO_CONTROL, 0);}/* http://bcm-specs.sipsolutions.net/EnableMac */void b43legacy_mac_enable(struct b43legacy_wldev *dev){	dev->mac_suspended--;	B43legacy_WARN_ON(dev->mac_suspended < 0);	if (dev->mac_suspended == 0) {		b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,				  b43legacy_read32(dev,				  B43legacy_MMIO_STATUS_BITFIELD)				  | B43legacy_SBF_MAC_ENABLED);		b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON,				  B43legacy_IRQ_MAC_SUSPENDED);		/* the next two are dummy reads */		b43legacy_read32(dev, B43legacy_MMIO_STATUS_BITFIELD);		b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);		b43legacy_power_saving_ctl_bits(dev, -1, -1);	}}/* http://bcm-specs.sipsolutions.net/SuspendMAC */void b43legacy_mac_suspend(struct b43legacy_wldev *dev){	int i;	u32 tmp;	B43legacy_WARN_ON(dev->mac_suspended < 0);	if (dev->mac_suspended == 0) {		b43legacy_power_saving_ctl_bits(dev, -1, 1);		b43legacy_write32(dev, B43legacy_MMIO_STATUS_BITFIELD,				  b43legacy_read32(dev,				  B43legacy_MMIO_STATUS_BITFIELD)				  & ~B43legacy_SBF_MAC_ENABLED);		b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON);		for (i = 10000; i; i--) {			tmp = b43legacy_read32(dev,					       B43legacy_MMIO_GEN_IRQ_REASON);			if (tmp & B43legacy_IRQ_MAC_SUSPENDED)				goto out;			udelay(1);		}		b43legacyerr(dev->wl, "MAC suspend failed\n");	}out:	dev->mac_suspended++;}static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev){	struct b43legacy_wl *wl = dev->wl;	u32 ctl;	u16 cfp_pretbtt;	ctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL);	/* Reset status to STA infrastructure mode. */	ctl &= ~B43legacy_MACCTL_AP;	ctl &= ~B43legacy_MACCTL_KEEP_CTL;	ctl &= ~B43legacy_MACCTL_KEEP_BADPLCP;	ctl &= ~B43legacy_MACCTL_KEEP_BAD;	ctl &= ~B43legacy_MACCTL_PROMISC;	ctl &= ~B43legacy_MACCTL_BEACPROMISC;

⌨️ 快捷键说明

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