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

📄 main.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 5 页
字号:
static void pio_irq_workaround(struct b43_wldev *dev, u16 base, int queueidx){	u16 rxctl;	rxctl = b43_read16(dev, base + B43_PIO_RXCTL);	if (rxctl & B43_PIO_RXCTL_DATAAVAILABLE)		dev->dma_reason[queueidx] |= B43_DMAIRQ_RX_DONE;	else		dev->dma_reason[queueidx] &= ~B43_DMAIRQ_RX_DONE;}static void b43_interrupt_ack(struct b43_wldev *dev, u32 reason){	if (b43_using_pio(dev) &&	    (dev->dev->id.revision < 3) &&	    (!(reason & B43_IRQ_PIO_WORKAROUND))) {		/* Apply a PIO specific workaround to the dma_reasons */		pio_irq_workaround(dev, B43_MMIO_PIO1_BASE, 0);		pio_irq_workaround(dev, B43_MMIO_PIO2_BASE, 1);		pio_irq_workaround(dev, B43_MMIO_PIO3_BASE, 2);		pio_irq_workaround(dev, B43_MMIO_PIO4_BASE, 3);	}	b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason);	b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]);	b43_write32(dev, B43_MMIO_DMA1_REASON, dev->dma_reason[1]);	b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]);	b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]);	b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]);	b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]);}/* Interrupt handler top-half */static irqreturn_t b43_interrupt_handler(int irq, void *dev_id){	irqreturn_t ret = IRQ_NONE;	struct b43_wldev *dev = dev_id;	u32 reason;	if (!dev)		return IRQ_NONE;	spin_lock(&dev->wl->irq_lock);	if (b43_status(dev) < B43_STAT_STARTED)		goto out;	reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);	if (reason == 0xffffffff)	/* shared IRQ */		goto out;	ret = IRQ_HANDLED;	reason &= b43_read32(dev, B43_MMIO_GEN_IRQ_MASK);	if (!reason)		goto out;	dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)	    & 0x0001DC00;	dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON)	    & 0x0000DC00;	dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON)	    & 0x0000DC00;	dev->dma_reason[3] = b43_read32(dev, B43_MMIO_DMA3_REASON)	    & 0x0001DC00;	dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON)	    & 0x0000DC00;	dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON)	    & 0x0000DC00;	b43_interrupt_ack(dev, reason);	/* disable all IRQs. They are enabled again in the bottom half. */	dev->irq_savedstate = b43_interrupt_disable(dev, B43_IRQ_ALL);	/* save the reason code and call our bottom half. */	dev->irq_reason = reason;	tasklet_schedule(&dev->isr_tasklet);      out:	mmiowb();	spin_unlock(&dev->wl->irq_lock);	return ret;}static void b43_release_firmware(struct b43_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 b43_print_fw_helptext(struct b43_wl *wl){	b43err(wl, "You must go to "	       "http://linuxwireless.org/en/users/Drivers/b43#devicefirmware "	       "and download the correct firmware (version 4).\n");}static int do_request_fw(struct b43_wldev *dev,			 const char *name,			 const struct firmware **fw){	char path[sizeof(modparam_fwpostfix) + 32];	struct b43_fw_header *hdr;	u32 size;	int err;	if (!name)		return 0;	snprintf(path, ARRAY_SIZE(path),		 "b43%s/%s.fw",		 modparam_fwpostfix, name);	err = request_firmware(fw, path, dev->dev->dev);	if (err) {		b43err(dev->wl, "Firmware file \"%s\" not found "		       "or load failed.\n", path);		return err;	}	if ((*fw)->size < sizeof(struct b43_fw_header))		goto err_format;	hdr = (struct b43_fw_header *)((*fw)->data);	switch (hdr->type) {	case B43_FW_TYPE_UCODE:	case B43_FW_TYPE_PCM:		size = be32_to_cpu(hdr->size);		if (size != (*fw)->size - sizeof(struct b43_fw_header))			goto err_format;		/* fallthrough */	case B43_FW_TYPE_IV:		if (hdr->ver != 1)			goto err_format;		break;	default:		goto err_format;	}	return err;err_format:	b43err(dev->wl, "Firmware file \"%s\" format error.\n", path);	return -EPROTO;}static int b43_request_firmware(struct b43_wldev *dev){	struct b43_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 >= 5) && (rev <= 10))			filename = "ucode5";		else if ((rev >= 11) && (rev <= 12))			filename = "ucode11";		else if (rev >= 13)			filename = "ucode13";		else			goto err_no_ucode;		err = do_request_fw(dev, filename, &fw->ucode);		if (err)			goto err_load;	}	if (!fw->pcm) {		if ((rev >= 5) && (rev <= 10))			filename = "pcm5";		else if (rev >= 11)			filename = NULL;		else			goto err_no_pcm;		err = do_request_fw(dev, filename, &fw->pcm);		if (err)			goto err_load;	}	if (!fw->initvals) {		switch (dev->phy.type) {		case B43_PHYTYPE_A:			if ((rev >= 5) && (rev <= 10)) {				if (tmshigh & B43_TMSHIGH_GPHY)					filename = "a0g1initvals5";				else					filename = "a0g0initvals5";			} else				goto err_no_initvals;			break;		case B43_PHYTYPE_G:			if ((rev >= 5) && (rev <= 10))				filename = "b0g0initvals5";			else if (rev >= 13)				filename = "lp0initvals13";			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 B43_PHYTYPE_A:			if ((rev >= 5) && (rev <= 10)) {				if (tmshigh & B43_TMSHIGH_GPHY)					filename = "a0g1bsinitvals5";				else					filename = "a0g0bsinitvals5";			} else if (rev >= 11)				filename = NULL;			else				goto err_no_initvals;			break;		case B43_PHYTYPE_G:			if ((rev >= 5) && (rev <= 10))				filename = "b0g0bsinitvals5";			else if (rev >= 11)				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:	b43_print_fw_helptext(dev->wl);	goto error;err_no_ucode:	err = -ENODEV;	b43err(dev->wl, "No microcode available for core rev %u\n", rev);	goto error;err_no_pcm:	err = -ENODEV;	b43err(dev->wl, "No PCM available for core rev %u\n", rev);	goto error;err_no_initvals:	err = -ENODEV;	b43err(dev->wl, "No Initial Values firmware file for PHY %u, "	       "core rev %u\n", dev->phy.type, rev);	goto error;error:	b43_release_firmware(dev);	return err;}static int b43_upload_microcode(struct b43_wldev *dev){	const size_t hdr_len = sizeof(struct b43_fw_header);	const __be32 *data;	unsigned int i, len;	u16 fwrev, fwpatch, fwdate, 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);	b43_shm_control_word(dev, B43_SHM_UCODE | B43_SHM_AUTOINC_W, 0x0000);	for (i = 0; i < len; i++) {		b43_write32(dev, B43_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);		b43_shm_control_word(dev, B43_SHM_HW, 0x01EA);		b43_write32(dev, B43_MMIO_SHM_DATA, 0x00004000);		/* No need for autoinc bit in SHM_HW */		b43_shm_control_word(dev, B43_SHM_HW, 0x01EB);		for (i = 0; i < len; i++) {			b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i]));			udelay(10);		}	}	b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_ALL);	b43_write32(dev, B43_MMIO_MACCTL,		    B43_MACCTL_PSM_RUN |		    B43_MACCTL_IHR_ENABLED | B43_MACCTL_INFRA);	/* Wait for the microcode to load and respond */	i = 0;	while (1) {		tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);		if (tmp == B43_IRQ_MAC_SUSPENDED)			break;		i++;		if (i >= 50) {			b43err(dev->wl, "Microcode not responding\n");			b43_print_fw_helptext(dev->wl);			err = -ENODEV;			goto out;		}		udelay(10);	}	b43_read32(dev, B43_MMIO_GEN_IRQ_REASON);	/* dummy read */	/* Get and check the revisions. */	fwrev = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEREV);	fwpatch = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEPATCH);	fwdate = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEDATE);	fwtime = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODETIME);	if (fwrev <= 0x128) {		b43err(dev->wl, "YOUR FIRMWARE IS TOO OLD. Firmware from "		       "binary drivers older than version 4.x is unsupported. "		       "You must upgrade your firmware files.\n");		b43_print_fw_helptext(dev->wl);		b43_write32(dev, B43_MMIO_MACCTL, 0);		err = -EOPNOTSUPP;		goto out;	}	if (fwrev > 351) {		b43err(dev->wl, "YOUR FIRMWARE IS TOO NEW. Please downgrade your "		       "firmware.\n");		b43err(dev->wl, "Use this firmware tarball: "		       "http://downloads.openwrt.org/sources/broadcom-wl-4.80.53.0.tar.bz2\n");		b43err(dev->wl, "Use this b43-fwcutter tarball: "		       "http://bu3sch.de/b43/fwcutter/b43-fwcutter-009.tar.bz2\n");		b43err(dev->wl, "Read, understand and _do_ what this message says, please.\n");		b43_write32(dev, B43_MMIO_MACCTL, 0);		err = -EOPNOTSUPP;		goto out;	}	b43dbg(dev->wl, "Loading firmware version %u.%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 b43_write_initvals(struct b43_wldev *dev,			      const struct b43_iv *ivals,			      size_t count,			      size_t array_size){	const struct b43_iv *iv;	u16 offset;	size_t i;	bool bit32;	BUILD_BUG_ON(sizeof(struct b43_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 & B43_IV_32BIT);		offset &= B43_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));			b43_write32(dev, offset, value);			iv = (const struct b43_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);			b43_write16(dev, offset, value);			iv = (const struct b43_iv *)((const uint8_t *)iv +							sizeof(__be16) +							sizeof(__be16));		}	}	if (array_size)		goto err_format;	return 0;err_format:	b43err(dev->wl, "Initial Values Firmware file-format error.\n");	b43_print_fw_helptext(dev->wl);	return -EPROTO;}static int b43_upload_initvals(struct b43_wldev *dev){	const size_t hdr_len = sizeof(struct b43_fw_header);	const struct b43_fw_header *hdr;	struct b43_firmware *fw = &dev->fw;	const struct b43_iv *ivals;	size_t count;	int err;	hdr = (const struct b43_fw_header *)(fw->initvals->data);	ivals = (const struct b43_iv *)(fw->initvals->data + hdr_len);	count = be32_to_cpu(hdr->size);	err = b43_write_initvals(dev, ivals, count,				 fw->initvals->size - hdr_len);	if (err)		goto out;	if (fw->initvals_band) {		hdr = (const struct b43_fw_header *)(fw->initvals_band->data);		ivals = (const struct b43_iv *)(fw->initvals_band->data + hdr_len);		count = be32_to_cpu(hdr->size);		err = b43_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 b43_gpio_init(struct b43_wldev *dev){	struct ssb_bus *bus = dev->dev->bus;	struct ssb_device *gpiodev, *pcidev = NULL;	u32 mask, set;	b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL)		    & ~B43_MACCTL_GPOUTSMSK);	b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK)		    | 0x000F);	mask = 0x0000001F;	set = 0x0000000F;	if (dev->dev->bus->chip_id == 0x4301) {		mask |= 0x0060;		set |= 0x0060;	}	if (0 /* FIXME: conditional unknown */ ) {		b43_write16(dev, B43_MMIO_GPIO_MASK,			    b43_read16(dev, B43_MMIO_GPIO_MASK)			    | 0x0100);		mask |= 0x0180;		set |= 0x0180;	}	if (dev->dev->bus->sprom.r1.boardflags_lo & B43_BFL_PACTRL) {		b43_write16(dev, B43_MMIO_GPIO_MASK,			    b43_read16(dev, B43_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, B43_GPIO_CONTROL,

⌨️ 快捷键说明

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