mirror of
git://projects.qi-hardware.com/openwrt-xburst.git
synced 2024-11-23 23:16:16 +02:00
update the acx driver
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@10178 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
parent
5c8527e331
commit
b45c92bdd0
@ -10,12 +10,12 @@ include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=acx-mac80211
|
||||
PKG_VERSION:=20071003
|
||||
PKG_VERSION:=20080112
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
|
||||
PKG_SOURCE_URL:=@SF/acx100
|
||||
PKG_MD5SUM:=dff7b396299001724e522d3ccf79c883
|
||||
PKG_MD5SUM:=3d2253c3a639ebccf06113be888118fb
|
||||
|
||||
PKG_FW_NAME:=tiacx111c16
|
||||
PKG_FW_URL:=http://teknoraver.campuslife.it/software/acx-mac80211/
|
||||
|
@ -1,555 +0,0 @@
|
||||
diff -Nru 1/acx_struct.h 2/acx_struct.h
|
||||
--- 1/acx_struct.h 2007-10-03 23:42:39.000000000 +0800
|
||||
+++ 2/acx_struct.h 2007-10-06 01:15:32.000000000 +0800
|
||||
@@ -1425,7 +1425,13 @@
|
||||
|
||||
const u16 *io; /* points to ACX100 or ACX111 PCI I/O register address set */
|
||||
|
||||
+#ifdef CONFIG_PCI
|
||||
struct pci_dev *pdev;
|
||||
+#endif
|
||||
+#ifdef CONFIG_VLYNQ
|
||||
+ struct vlynq_device *vdev;
|
||||
+#endif
|
||||
+ struct device *bus_dev;
|
||||
|
||||
unsigned long membase;
|
||||
unsigned long membase2;
|
||||
diff -Nru 1/pci.c 2/pci.c
|
||||
--- 1/pci.c 2007-10-03 23:42:39.000000000 +0800
|
||||
+++ 2/pci.c 2007-10-06 01:15:32.000000000 +0800
|
||||
@@ -33,11 +33,15 @@
|
||||
#include <linux/ethtool.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/workqueue.h>
|
||||
+#ifdef CONFIG_VLYNQ
|
||||
+#include <linux/vlynq.h>
|
||||
+#endif
|
||||
|
||||
#include "acx.h"
|
||||
|
||||
/***********************************************************************
|
||||
*/
|
||||
+#ifdef CONFIG_PCI
|
||||
#define PCI_TYPE (PCI_USES_MEM | PCI_ADDR0 | PCI_NO_ACPI_WAKE)
|
||||
#define PCI_ACX100_REGION1 0x01
|
||||
#define PCI_ACX100_REGION1_SIZE 0x1000 /* Memory size - 4K bytes */
|
||||
@@ -74,7 +78,7 @@
|
||||
#define PCI_UNKNOWN 5
|
||||
#define PCI_POWER_ERROR -1
|
||||
#endif
|
||||
-
|
||||
+#endif /* CONFIG_PCI */
|
||||
/***********************************************************************
|
||||
*/
|
||||
|
||||
@@ -87,12 +91,6 @@
|
||||
static void acxpci_s_up(struct ieee80211_hw *hw);
|
||||
static void acxpci_s_down(struct ieee80211_hw *hw);
|
||||
|
||||
-void acxpci_put_devname(acx_device_t *adev, struct ethtool_drvinfo *info)
|
||||
-{
|
||||
-
|
||||
- strncpy(info->bus_info,pci_name(adev->pdev), ETHTOOL_BUSINFO_LEN);
|
||||
-}
|
||||
-
|
||||
/***********************************************************************
|
||||
** Register access
|
||||
**
|
||||
@@ -605,12 +603,12 @@
|
||||
snprintf(filename, sizeof(filename), "tiacx1%02dc%02X",
|
||||
IS_ACX111(adev) * 11, adev->radio_type);
|
||||
|
||||
- fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
|
||||
+ fw_image = acx_s_read_fw(adev->bus_dev, filename, &file_size);
|
||||
if (!fw_image) {
|
||||
adev->need_radio_fw = 1;
|
||||
filename[sizeof("tiacx1NN") - 1] = '\0';
|
||||
fw_image =
|
||||
- acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
|
||||
+ acx_s_read_fw(adev->bus_dev, filename, &file_size);
|
||||
if (!fw_image) {
|
||||
FN_EXIT1(NOT_OK);
|
||||
return NOT_OK;
|
||||
@@ -670,7 +668,7 @@
|
||||
|
||||
snprintf(filename, sizeof(filename), "tiacx1%02dr%02X",
|
||||
IS_ACX111(adev) * 11, adev->radio_type);
|
||||
- radio_image = acx_s_read_fw(&adev->pdev->dev, filename, &size);
|
||||
+ radio_image = acx_s_read_fw(adev->bus_dev, filename, &size);
|
||||
if (!radio_image) {
|
||||
printk("acx: can't load radio module '%s'\n", filename);
|
||||
goto fail;
|
||||
@@ -886,7 +884,9 @@
|
||||
|
||||
acx_lock(adev, flags);
|
||||
|
||||
+#ifdef CONFIG_PCI
|
||||
acxpci_l_reset_mac(adev);
|
||||
+#endif
|
||||
|
||||
ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
|
||||
if (!ecpu_ctrl) {
|
||||
@@ -1426,6 +1426,7 @@
|
||||
};
|
||||
|
||||
|
||||
+#ifdef CONFIG_PCI
|
||||
static int __devinit
|
||||
acxpci_e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
@@ -1477,6 +1478,7 @@
|
||||
/* acx_sem_lock(adev); */
|
||||
adev->ieee = ieee;
|
||||
adev->pdev = pdev;
|
||||
+ adev->bus_dev = &pdev->dev;
|
||||
adev->dev_type = DEVTYPE_PCI;
|
||||
|
||||
/** Finished with private interface **/
|
||||
@@ -1916,7 +1918,7 @@
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
-
|
||||
+#endif /* CONFIG_PCI */
|
||||
|
||||
/***********************************************************************
|
||||
** acxpci_s_up
|
||||
@@ -1998,7 +2000,7 @@
|
||||
/* then wait until interrupts have finished executing on other CPUs */
|
||||
acx_lock(adev, flags);
|
||||
disable_acx_irq(adev);
|
||||
- synchronize_irq(adev->pdev->irq);
|
||||
+ synchronize_irq(adev->irq);
|
||||
acx_unlock(adev, flags);
|
||||
|
||||
/* we really don't want to have an asynchronous tasklet disturb us
|
||||
@@ -3449,8 +3451,7 @@
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
- ptr = dma_alloc_coherent(adev->pdev ? &adev->pdev->dev : NULL,
|
||||
- size, phy, GFP_KERNEL);
|
||||
+ ptr = dma_alloc_coherent(adev->bus_dev, size, phy, GFP_KERNEL);
|
||||
|
||||
if (ptr) {
|
||||
log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
|
||||
@@ -4016,10 +4017,370 @@
|
||||
return OK;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_VLYNQ
|
||||
+struct vlynq_reg_config {
|
||||
+ u32 offset;
|
||||
+ u32 value;
|
||||
+};
|
||||
+
|
||||
+struct vlynq_known {
|
||||
+ u32 chip_id;
|
||||
+ char name[32];
|
||||
+ struct vlynq_mapping rx_mapping[4];
|
||||
+ int irq;
|
||||
+ int irq_type;
|
||||
+ int num_regs;
|
||||
+ struct vlynq_reg_config regs[10];
|
||||
+};
|
||||
+
|
||||
+#define CHIP_TNETW1130 0x00000009
|
||||
+#define CHIP_TNETW1350 0x00000029
|
||||
+
|
||||
+static struct vlynq_known known_devices[] = {
|
||||
+ {
|
||||
+ .chip_id = CHIP_TNETW1130, .name = "TI TNETW1130",
|
||||
+ .rx_mapping = {
|
||||
+ { .size = 0x22000, .offset = 0xf0000000 },
|
||||
+ { .size = 0x40000, .offset = 0xc0000000 },
|
||||
+ { .size = 0x0, .offset = 0x0 },
|
||||
+ { .size = 0x0, .offset = 0x0 },
|
||||
+ },
|
||||
+ .irq = 0,
|
||||
+ .irq_type = IRQ_TYPE_EDGE_RISING,
|
||||
+ .num_regs = 5,
|
||||
+ .regs = {
|
||||
+ {
|
||||
+ .offset = 0x790,
|
||||
+ .value = (0xd0000000 - PHYS_OFFSET)
|
||||
+ },
|
||||
+ {
|
||||
+ .offset = 0x794,
|
||||
+ .value = (0xd0000000 - PHYS_OFFSET)
|
||||
+ },
|
||||
+ { .offset = 0x740, .value = 0 },
|
||||
+ { .offset = 0x744, .value = 0x00010000 },
|
||||
+ { .offset = 0x764, .value = 0x00010000 },
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .chip_id = CHIP_TNETW1350, .name = "TI TNETW1350",
|
||||
+ .rx_mapping = {
|
||||
+ { .size = 0x100000, .offset = 0x00300000 },
|
||||
+ { .size = 0x80000, .offset = 0x00000000 },
|
||||
+ { .size = 0x0, .offset = 0x0 },
|
||||
+ { .size = 0x0, .offset = 0x0 },
|
||||
+ },
|
||||
+ .irq = 0,
|
||||
+ .irq_type = IRQ_TYPE_EDGE_RISING,
|
||||
+ .num_regs = 5,
|
||||
+ .regs = {
|
||||
+ {
|
||||
+ .offset = 0x790,
|
||||
+ .value = (0x60000000 - PHYS_OFFSET)
|
||||
+ },
|
||||
+ {
|
||||
+ .offset = 0x794,
|
||||
+ .value = (0x60000000 - PHYS_OFFSET)
|
||||
+ },
|
||||
+ { .offset = 0x740, .value = 0 },
|
||||
+ { .offset = 0x744, .value = 0x00010000 },
|
||||
+ { .offset = 0x764, .value = 0x00010000 },
|
||||
+ },
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct vlynq_device_id acx_vlynq_id[] = {
|
||||
+ { CHIP_TNETW1130, vlynq_div_auto, 0 },
|
||||
+ { CHIP_TNETW1350, vlynq_div_auto, 1 },
|
||||
+ { 0, 0, 0 },
|
||||
+};
|
||||
+
|
||||
+static __devinit int vlynq_probe(struct vlynq_device *vdev,
|
||||
+ struct vlynq_device_id *id)
|
||||
+{
|
||||
+ int result = -EIO, i;
|
||||
+ u32 addr;
|
||||
+ struct ieee80211_hw *ieee;
|
||||
+ acx_device_t *adev = NULL;
|
||||
+ acx111_ie_configoption_t co;
|
||||
+ struct vlynq_mapping mapping[4] = { { 0, }, };
|
||||
+ struct vlynq_known *match = NULL;
|
||||
+
|
||||
+ FN_ENTER;
|
||||
+ result = vlynq_enable_device(vdev);
|
||||
+ if (result)
|
||||
+ return result;
|
||||
+
|
||||
+ match = &known_devices[id->driver_data];
|
||||
+
|
||||
+ if (!match) {
|
||||
+ result = -ENODEV;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ mapping[0].offset = ARCH_PFN_OFFSET << PAGE_SHIFT;
|
||||
+ mapping[0].size = 0x02000000;
|
||||
+ vlynq_set_local_mapping(vdev, vdev->mem_start, mapping);
|
||||
+ vlynq_set_remote_mapping(vdev, 0, match->rx_mapping);
|
||||
+
|
||||
+ set_irq_type(vlynq_virq_to_irq(vdev, match->irq), match->irq_type);
|
||||
+
|
||||
+ addr = (u32)ioremap(vdev->mem_start, 0x1000);
|
||||
+ if (!addr) {
|
||||
+ printk(KERN_ERR "%s: failed to remap io memory\n",
|
||||
+ vdev->dev.bus_id);
|
||||
+ result = -ENXIO;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < match->num_regs; i++)
|
||||
+ iowrite32(match->regs[i].value,
|
||||
+ (u32 *)(addr + match->regs[i].offset));
|
||||
+
|
||||
+ iounmap((void *)addr);
|
||||
+
|
||||
+ ieee = ieee80211_alloc_hw(sizeof(struct acx_device), &acxpci_hw_ops);
|
||||
+ if (!ieee) {
|
||||
+ printk("acx: could not allocate ieee80211 structure %s\n",
|
||||
+ vdev->dev.bus_id);
|
||||
+ goto fail_alloc_netdev;
|
||||
+ }
|
||||
+ ieee->flags &= (~IEEE80211_HW_RX_INCLUDES_FCS &
|
||||
+ ~IEEE80211_HW_MONITOR_DURING_OPER) |
|
||||
+ IEEE80211_HW_WEP_INCLUDE_IV;
|
||||
+ ieee->queues = 1;
|
||||
+
|
||||
+ adev = ieee2adev(ieee);
|
||||
+
|
||||
+ memset(adev, 0, sizeof(*adev));
|
||||
+ /** Set up our private interface **/
|
||||
+ spin_lock_init(&adev->lock); /* initial state: unlocked */
|
||||
+ /* We do not start with downed sem: we want PARANOID_LOCKING to work */
|
||||
+ mutex_init(&adev->mutex);
|
||||
+ /* since nobody can see new netdev yet, we can as well
|
||||
+ ** just _presume_ that we're under sem (instead of actually taking it): */
|
||||
+ /* acx_sem_lock(adev); */
|
||||
+ adev->ieee = ieee;
|
||||
+ adev->vdev = vdev;
|
||||
+ adev->bus_dev = &vdev->dev;
|
||||
+ adev->dev_type = DEVTYPE_PCI;
|
||||
+
|
||||
+/** Finished with private interface **/
|
||||
+
|
||||
+ vlynq_set_drvdata(vdev, ieee);
|
||||
+ if (!request_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start, "acx")) {
|
||||
+ printk("acx: cannot reserve VLYNQ memory region\n");
|
||||
+ goto fail_request_mem_region;
|
||||
+ }
|
||||
+ adev->iobase = ioremap(vdev->mem_start, vdev->mem_end - vdev->mem_start);
|
||||
+ if (!adev->iobase) {
|
||||
+ printk("acx: ioremap() FAILED\n");
|
||||
+ goto fail_ioremap;
|
||||
+ }
|
||||
+ adev->iobase2 = adev->iobase + match->rx_mapping[0].size;
|
||||
+ adev->chip_type = CHIPTYPE_ACX111;
|
||||
+ adev->chip_name = match->name;
|
||||
+ adev->io = IO_ACX111;
|
||||
+ adev->irq = vlynq_virq_to_irq(vdev, match->irq);
|
||||
+
|
||||
+ printk("acx: found %s-based wireless network card at %s, irq:%d, "
|
||||
+ "phymem:0x%x, mem:0x%p\n",
|
||||
+ match->name, vdev->dev.bus_id, adev->irq,
|
||||
+ vdev->mem_start, adev->iobase);
|
||||
+ log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
|
||||
+
|
||||
+ if (0 == adev->irq) {
|
||||
+ printk("acx: can't use IRQ 0\n");
|
||||
+ goto fail_irq;
|
||||
+ }
|
||||
+ SET_IEEE80211_DEV(ieee, &vdev->dev);
|
||||
+
|
||||
+
|
||||
+ /* to find crashes due to weird driver access
|
||||
+ * to unconfigured interface (ifup) */
|
||||
+ adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
|
||||
+
|
||||
+
|
||||
+ /* ok, pci setup is finished, now start initializing the card */
|
||||
+
|
||||
+ /* NB: read_reg() reads may return bogus data before reset_dev(),
|
||||
+ * since the firmware which directly controls large parts of the I/O
|
||||
+ * registers isn't initialized yet.
|
||||
+ * acx100 seems to be more affected than acx111 */
|
||||
+ if (OK != acxpci_s_reset_dev(adev))
|
||||
+ goto fail_reset;
|
||||
+
|
||||
+ if (OK != acx_s_init_mac(adev))
|
||||
+ goto fail_init_mac;
|
||||
+
|
||||
+ acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
|
||||
+/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
|
||||
+ if (OK != acxpci_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
|
||||
+ goto fail_read_eeprom_version;
|
||||
+
|
||||
+ acx_s_parse_configoption(adev, &co);
|
||||
+ acx_s_set_defaults(adev);
|
||||
+ acx_s_get_firmware_version(adev); /* needs to be after acx_s_init_mac() */
|
||||
+ acx_display_hardware_details(adev);
|
||||
+
|
||||
+ /* Register the card, AFTER everything else has been set up,
|
||||
+ * since otherwise an ioctl could step on our feet due to
|
||||
+ * firmware operations happening in parallel or uninitialized data */
|
||||
+
|
||||
+
|
||||
+ acx_proc_register_entries(ieee);
|
||||
+
|
||||
+ /* Now we have our device, so make sure the kernel doesn't try
|
||||
+ * to send packets even though we're not associated to a network yet */
|
||||
+
|
||||
+ /* after register_netdev() userspace may start working with dev
|
||||
+ * (in particular, on other CPUs), we only need to up the sem */
|
||||
+ /* acx_sem_unlock(adev); */
|
||||
+
|
||||
+ printk("acx " ACX_RELEASE ": net device %s, driver compiled "
|
||||
+ "against wireless extensions %d and Linux %s\n",
|
||||
+ wiphy_name(adev->ieee->wiphy), WIRELESS_EXT, UTS_RELEASE);
|
||||
+
|
||||
+ MAC_COPY(adev->ieee->wiphy->perm_addr, adev->dev_addr);
|
||||
+
|
||||
+ log(L_IRQ | L_INIT, "using IRQ %d\n", adev->irq);
|
||||
+
|
||||
+/** done with board specific setup **/
|
||||
+
|
||||
+ acx_init_task_scheduler(adev);
|
||||
+ result = ieee80211_register_hw(adev->ieee);
|
||||
+ if (OK != result) {
|
||||
+ printk("acx: ieee80211_register_hw() FAILED: %d\n", result);
|
||||
+ goto fail_register_netdev;
|
||||
+ }
|
||||
+#if CMD_DISCOVERY
|
||||
+ great_inquisitor(adev);
|
||||
+#endif
|
||||
+
|
||||
+ result = OK;
|
||||
+ goto done;
|
||||
+
|
||||
+ /* error paths: undo everything in reverse order... */
|
||||
+
|
||||
+
|
||||
+ acxpci_s_delete_dma_regions(adev);
|
||||
+
|
||||
+ fail_init_mac:
|
||||
+ fail_read_eeprom_version:
|
||||
+ fail_reset:
|
||||
+
|
||||
+ fail_alloc_netdev:
|
||||
+ fail_irq:
|
||||
+
|
||||
+ iounmap(adev->iobase);
|
||||
+ fail_ioremap:
|
||||
+
|
||||
+ release_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start);
|
||||
+ fail_request_mem_region:
|
||||
+ fail_register_netdev:
|
||||
+ ieee80211_free_hw(ieee);
|
||||
+ fail:
|
||||
+ vlynq_disable_device(vdev);
|
||||
+ done:
|
||||
+ FN_EXIT1(result);
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+static void vlynq_remove(struct vlynq_device *vdev)
|
||||
+{
|
||||
+ struct ieee80211_hw *hw = vlynq_get_drvdata(vdev);
|
||||
+ acx_device_t *adev = ieee2adev(hw);
|
||||
+ unsigned long flags;
|
||||
+ FN_ENTER;
|
||||
+
|
||||
+ if (!hw) {
|
||||
+ log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
|
||||
+ __func__);
|
||||
+ goto end;
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ acx_lock(adev, flags);
|
||||
+ acx_unlock(adev, flags);
|
||||
+ adev->initialized = 0;
|
||||
+
|
||||
+ /* If device wasn't hot unplugged... */
|
||||
+ if (adev_present(adev)) {
|
||||
+
|
||||
+ acx_sem_lock(adev);
|
||||
+
|
||||
+ /* disable both Tx and Rx to shut radio down properly */
|
||||
+ if (adev->initialized) {
|
||||
+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
|
||||
+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
|
||||
+ }
|
||||
+ acx_lock(adev, flags);
|
||||
+ /* disable power LED to save power :-) */
|
||||
+ log(L_INIT, "switching off power LED to save power\n");
|
||||
+ acxpci_l_power_led(adev, 0);
|
||||
+ /* stop our eCPU */
|
||||
+ acx_unlock(adev, flags);
|
||||
+
|
||||
+ acx_sem_unlock(adev);
|
||||
+ }
|
||||
+
|
||||
+ /* unregister the device to not let the kernel
|
||||
+ * (e.g. ioctls) access a half-deconfigured device
|
||||
+ * NB: this will cause acxpci_e_close() to be called,
|
||||
+ * thus we shouldn't call it under sem!
|
||||
+ * Well, netdev did, but ieee80211 stack does not, so we
|
||||
+ * have to do so manually...
|
||||
+ */
|
||||
+ acxpci_e_close(hw);
|
||||
+ log(L_INIT, "removing device %s\n", wiphy_name(adev->ieee->wiphy));
|
||||
+ ieee80211_unregister_hw(adev->ieee);
|
||||
+
|
||||
+ /* unregister_netdev ensures that no references to us left.
|
||||
+ * For paranoid reasons we continue to follow the rules */
|
||||
+ acx_sem_lock(adev);
|
||||
+
|
||||
+ if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
|
||||
+ acxpci_s_down(hw);
|
||||
+ CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
|
||||
+ }
|
||||
+
|
||||
+ acx_proc_unregister_entries(adev->ieee);
|
||||
+
|
||||
+ /* finally, clean up PCI bus state */
|
||||
+ acxpci_s_delete_dma_regions(adev);
|
||||
+ if (adev->iobase)
|
||||
+ iounmap(adev->iobase);
|
||||
+ if (adev->iobase2)
|
||||
+ iounmap(adev->iobase2);
|
||||
+ release_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start);
|
||||
+
|
||||
+ /* remove dev registration */
|
||||
+
|
||||
+ acx_sem_unlock(adev);
|
||||
+ vlynq_disable_device(vdev);
|
||||
+
|
||||
+ /* Free netdev (quite late,
|
||||
+ * since otherwise we might get caught off-guard
|
||||
+ * by a netdev timeout handler execution
|
||||
+ * expecting to see a working dev...) */
|
||||
+ ieee80211_free_hw(adev->ieee);
|
||||
+
|
||||
+ end:
|
||||
+ FN_EXIT0;
|
||||
+}
|
||||
+
|
||||
+static struct vlynq_driver vlynq_acx = {
|
||||
+ .name = "acx_vlynq",
|
||||
+ .id_table = acx_vlynq_id,
|
||||
+ .probe = vlynq_probe,
|
||||
+ .remove = __devexit_p(vlynq_remove),
|
||||
+};
|
||||
+#endif
|
||||
|
||||
/***********************************************************************
|
||||
** Data for init_module/cleanup_module
|
||||
*/
|
||||
+#ifdef CONFIG_PCI
|
||||
static const struct pci_device_id acxpci_id_tbl[] __devinitdata = {
|
||||
{
|
||||
.vendor = PCI_VENDOR_ID_TI,
|
||||
@@ -4071,7 +4432,7 @@
|
||||
.resume = acxpci_e_resume
|
||||
#endif /* CONFIG_PM */
|
||||
};
|
||||
-
|
||||
+#endif /* CONFIG_PCI */
|
||||
|
||||
/***********************************************************************
|
||||
** acxpci_e_init_module
|
||||
@@ -4080,7 +4441,7 @@
|
||||
*/
|
||||
int __init acxpci_e_init_module(void)
|
||||
{
|
||||
- int res;
|
||||
+ int res = 0;
|
||||
|
||||
FN_ENTER;
|
||||
|
||||
@@ -4100,10 +4461,15 @@
|
||||
#endif
|
||||
log(L_INIT,
|
||||
"acx: " ENDIANNESS_STRING
|
||||
- "acx: PCI module " ACX_RELEASE " initialized, "
|
||||
+ "acx: PCI/VLYNQ module " ACX_RELEASE " initialized, "
|
||||
"waiting for cards to probe...\n");
|
||||
|
||||
+#ifdef CONFIG_PCI
|
||||
res = pci_register_driver(&acxpci_drv_id);
|
||||
+#endif
|
||||
+#ifdef CONFIG_VLYNQ
|
||||
+ res = vlynq_register_driver(&vlynq_acx);
|
||||
+#endif
|
||||
FN_EXIT1(res);
|
||||
return res;
|
||||
}
|
||||
@@ -4119,7 +4485,12 @@
|
||||
{
|
||||
FN_ENTER;
|
||||
|
||||
+#ifdef CONFIG_VLYNQ
|
||||
+ vlynq_unregister_driver(&vlynq_acx);
|
||||
+#endif
|
||||
+#ifdef CONFIG_PCI
|
||||
pci_unregister_driver(&acxpci_drv_id);
|
||||
+#endif
|
||||
|
||||
FN_EXIT0;
|
||||
}
|
@ -1,178 +0,0 @@
|
||||
Index: acx-mac80211-20071003/common.c
|
||||
===================================================================
|
||||
--- acx-mac80211-20071003.orig/common.c 2007-10-15 21:33:40.000000000 +0800
|
||||
+++ acx-mac80211-20071003/common.c 2007-10-16 10:01:58.000000000 +0800
|
||||
@@ -1683,7 +1683,9 @@
|
||||
*/
|
||||
void
|
||||
acx_i_set_multicast_list(struct ieee80211_hw *hw,
|
||||
- unsigned short netflags, int mc_count)
|
||||
+ unsigned int changed_flags,
|
||||
+ unsigned int *total_flags,
|
||||
+ int mc_count, struct dev_addr_list *mc_list)
|
||||
{
|
||||
acx_device_t *adev = ieee2adev(hw);
|
||||
unsigned long flags;
|
||||
@@ -1692,9 +1694,12 @@
|
||||
|
||||
acx_lock(adev, flags);
|
||||
|
||||
+ *total_flags &= (FIF_PROMISC_IN_BSS | FIF_ALLMULTI);
|
||||
+ if ((changed_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) == 0)
|
||||
+ return;
|
||||
/* firmwares don't have allmulti capability,
|
||||
* so just use promiscuous mode instead in this case. */
|
||||
- if (netflags & (IFF_PROMISC | IFF_ALLMULTI)) {
|
||||
+ if (*total_flags) {
|
||||
SET_BIT(adev->rx_config_1, RX_CFG1_RCV_PROMISCUOUS);
|
||||
CLEAR_BIT(adev->rx_config_1, RX_CFG1_FILTER_ALL_MULTI);
|
||||
SET_BIT(adev->set_mask, SET_RXCONFIG);
|
||||
@@ -4523,8 +4528,8 @@
|
||||
*/
|
||||
|
||||
int acx_net_set_key(struct ieee80211_hw *ieee,
|
||||
- set_key_cmd cmd,
|
||||
- u8 * addr, struct ieee80211_key_conf *key, int aid)
|
||||
+ enum set_key_cmd cmd, const u8 *local_addr,
|
||||
+ const u8 * addr, struct ieee80211_key_conf *key)
|
||||
{
|
||||
// return 0;
|
||||
struct acx_device *adev = ieee2adev(ieee);
|
||||
@@ -4536,11 +4541,11 @@
|
||||
// TODO();
|
||||
switch (key->alg) {
|
||||
default:
|
||||
- case ALG_NONE:
|
||||
+/* case ALG_NONE:
|
||||
case ALG_NULL:
|
||||
algorithm = ACX_SEC_ALGO_NONE;
|
||||
break;
|
||||
- case ALG_WEP:
|
||||
+*/ case ALG_WEP:
|
||||
if (key->keylen == 5)
|
||||
algorithm = ACX_SEC_ALGO_WEP;
|
||||
else
|
||||
@@ -4565,20 +4570,21 @@
|
||||
if (err)
|
||||
goto out_unlock;
|
||||
key->hw_key_idx = index;
|
||||
- CLEAR_BIT(key->flags, IEEE80211_KEY_FORCE_SW_ENCRYPT);
|
||||
- if (CHECK_BIT(key->flags, IEEE80211_KEY_DEFAULT_TX_KEY))
|
||||
- adev->default_key_idx = index;
|
||||
+/* CLEAR_BIT(key->flags, IEEE80211_KEY_FORCE_SW_ENCRYPT);*/
|
||||
+/* if (CHECK_BIT(key->flags, IEEE80211_KEY_DEFAULT_TX_KEY))
|
||||
+ adev->default_key_idx = index;*/
|
||||
+ SET_BIT(key->flags, IEEE80211_KEY_FLAG_GENERATE_IV);
|
||||
adev->key[index].enabled = 1;
|
||||
break;
|
||||
case DISABLE_KEY:
|
||||
adev->key[index].enabled = 0;
|
||||
err = 0;
|
||||
break;
|
||||
- case REMOVE_ALL_KEYS:
|
||||
+/* case REMOVE_ALL_KEYS:
|
||||
acx_clear_keys(adev);
|
||||
err = 0;
|
||||
break;
|
||||
- /* case ENABLE_COMPRESSION:
|
||||
+*/ /* case ENABLE_COMPRESSION:
|
||||
case DISABLE_COMPRESSION:
|
||||
err = 0;
|
||||
break; */
|
||||
Index: acx-mac80211-20071003/pci.c
|
||||
===================================================================
|
||||
--- acx-mac80211-20071003.orig/pci.c 2007-10-15 21:33:40.000000000 +0800
|
||||
+++ acx-mac80211-20071003/pci.c 2007-10-15 21:34:29.000000000 +0800
|
||||
@@ -87,7 +87,7 @@
|
||||
static void disable_acx_irq(acx_device_t * adev);
|
||||
|
||||
static int acxpci_e_open(struct ieee80211_hw *hw);
|
||||
-static int acxpci_e_close(struct ieee80211_hw *hw);
|
||||
+static void acxpci_e_close(struct ieee80211_hw *hw);
|
||||
static void acxpci_s_up(struct ieee80211_hw *hw);
|
||||
static void acxpci_s_down(struct ieee80211_hw *hw);
|
||||
|
||||
@@ -1414,12 +1414,12 @@
|
||||
.conf_tx = acx_net_conf_tx,
|
||||
.add_interface = acx_add_interface,
|
||||
.remove_interface = acx_remove_interface,
|
||||
- .open = acxpci_e_open,
|
||||
+ .start = acxpci_e_open,
|
||||
.stop = acxpci_e_close,
|
||||
- .reset = acx_net_reset,
|
||||
+/* .reset = acx_net_reset,*/
|
||||
.config = acx_net_config,
|
||||
.config_interface = acx_config_interface,
|
||||
- .set_multicast_list = acx_i_set_multicast_list,
|
||||
+ .configure_filter = acx_i_set_multicast_list,
|
||||
.set_key = acx_net_set_key,
|
||||
.get_stats = acx_e_get_stats,
|
||||
.get_tx_stats = acx_net_get_tx_stats,
|
||||
@@ -1454,9 +1454,7 @@
|
||||
pci_name(pdev));
|
||||
goto fail_alloc_netdev;
|
||||
}
|
||||
- ieee->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS &
|
||||
- ~IEEE80211_HW_MONITOR_DURING_OPER |
|
||||
- IEEE80211_HW_WEP_INCLUDE_IV;
|
||||
+ ieee->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
|
||||
ieee->queues = 1;
|
||||
|
||||
/* (NB: memsets to 0 entire area) */
|
||||
@@ -2113,7 +2111,7 @@
|
||||
** >0 f/w reported error
|
||||
** <0 driver reported error
|
||||
*/
|
||||
-static int acxpci_e_close(struct ieee80211_hw *hw)
|
||||
+static void acxpci_e_close(struct ieee80211_hw *hw)
|
||||
{
|
||||
acx_device_t *adev = ieee2adev(hw);
|
||||
unsigned long flags;
|
||||
@@ -2142,7 +2140,6 @@
|
||||
|
||||
log(L_INIT, "closed device\n");
|
||||
FN_EXIT0;
|
||||
- return OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -4145,9 +4142,7 @@
|
||||
vdev->dev.bus_id);
|
||||
goto fail_alloc_netdev;
|
||||
}
|
||||
- ieee->flags &= (~IEEE80211_HW_RX_INCLUDES_FCS &
|
||||
- ~IEEE80211_HW_MONITOR_DURING_OPER) |
|
||||
- IEEE80211_HW_WEP_INCLUDE_IV;
|
||||
+ ieee->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS;
|
||||
ieee->queues = 1;
|
||||
|
||||
adev = ieee2adev(ieee);
|
||||
Index: acx-mac80211-20071003/acx_func.h
|
||||
===================================================================
|
||||
--- acx-mac80211-20071003.orig/acx_func.h 2007-10-15 21:33:40.000000000 +0800
|
||||
+++ acx-mac80211-20071003/acx_func.h 2007-10-15 21:36:01.000000000 +0800
|
||||
@@ -610,10 +610,9 @@
|
||||
struct ieee80211_if_init_conf *conf);
|
||||
int acx_net_reset(struct ieee80211_hw* ieee);
|
||||
int acx_net_set_key(struct ieee80211_hw *hw,
|
||||
- set_key_cmd cmd,
|
||||
- u8 *addr,
|
||||
- struct ieee80211_key_conf *key,
|
||||
- int aid);
|
||||
+ enum set_key_cmd cmd,
|
||||
+ const u8 *local_addr, const u8 *addr,
|
||||
+ struct ieee80211_key_conf *key);
|
||||
int acx_config_interface(struct ieee80211_hw* ieee, int if_id,
|
||||
struct ieee80211_if_conf *conf);
|
||||
int acx_net_config(struct ieee80211_hw* ieee, struct ieee80211_conf *conf);
|
||||
@@ -625,7 +624,9 @@
|
||||
int acxpci_s_reset_dev(acx_device_t *adev);
|
||||
void acx_e_after_interrupt_task(struct work_struct* work);
|
||||
void acx_i_set_multicast_list(struct ieee80211_hw *hw,
|
||||
- unsigned short netflags, int mc_count);
|
||||
+ unsigned int changed_flags,
|
||||
+ unsigned int *total_flags,
|
||||
+ int mc_count, struct dev_addr_list *mc_list);
|
||||
|
||||
/*** End DeviceScape Functions **/
|
||||
|
@ -10,12 +10,12 @@ include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=acx
|
||||
PKG_VERSION:=20071003
|
||||
PKG_RELEASE:=2
|
||||
PKG_VERSION:=20080112
|
||||
PKG_RELEASE:=1
|
||||
|
||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
|
||||
PKG_SOURCE_URL:=@SF/acx100
|
||||
PKG_MD5SUM:=09cbaa558e1850d4996e7083d8b7bb93
|
||||
PKG_MD5SUM:=b376b5359ef15da589ef17387a6b37d3
|
||||
|
||||
PKG_FW_NAME:=tiacx111c16
|
||||
PKG_FW_URL:=http://teknoraver.campuslife.it/software/acx-mac80211/
|
||||
|
@ -1,20 +0,0 @@
|
||||
Index: acx-20070101/pci.c
|
||||
===================================================================
|
||||
--- acx-20070101.orig/pci.c 2007-06-04 13:22:42.489395912 +0200
|
||||
+++ acx-20070101/pci.c 2007-06-04 13:22:42.557385576 +0200
|
||||
@@ -925,10 +925,13 @@
|
||||
|
||||
acx_lock(adev, flags);
|
||||
|
||||
- acxpci_l_reset_mac(adev);
|
||||
-
|
||||
ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
|
||||
if (!ecpu_ctrl) {
|
||||
+ acxpci_l_reset_mac(adev);
|
||||
+ ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
|
||||
+ }
|
||||
+
|
||||
+ if (!ecpu_ctrl) {
|
||||
msg = "eCPU is already running. ";
|
||||
goto end_unlock;
|
||||
}
|
@ -1,557 +0,0 @@
|
||||
Binary files acx-20071003/.pci.c.swp and acx-20071003.new/.pci.c.swp differ
|
||||
diff -urN acx-20071003/acx_struct.h acx-20071003.new/acx_struct.h
|
||||
--- acx-20071003/acx_struct.h 2007-10-03 17:42:18.000000000 +0200
|
||||
+++ acx-20071003.new/acx_struct.h 2008-01-04 02:06:43.000000000 +0100
|
||||
@@ -1440,7 +1440,13 @@
|
||||
|
||||
const u16 *io; /* points to ACX100 or ACX111 PCI I/O register address set */
|
||||
|
||||
+#ifdef CONFIG_PCI
|
||||
struct pci_dev *pdev;
|
||||
+#endif
|
||||
+#ifdef CONFIG_VLYNQ
|
||||
+ struct vlynq_device *vdev;
|
||||
+#endif
|
||||
+ struct device *bus_dev;
|
||||
|
||||
unsigned long membase;
|
||||
unsigned long membase2;
|
||||
diff -urN acx-20071003/pci.c acx-20071003.new/pci.c
|
||||
--- acx-20071003/pci.c 2008-01-04 02:05:00.000000000 +0100
|
||||
+++ acx-20071003.new/pci.c 2008-01-04 03:10:42.000000000 +0100
|
||||
@@ -59,12 +59,17 @@
|
||||
#include <linux/pm.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
+#ifdef CONFIG_VLYNQ
|
||||
+#include <linux/vlynq.h>
|
||||
+#endif
|
||||
+
|
||||
|
||||
#include "acx.h"
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*/
|
||||
+#ifdef CONFIG_PCI
|
||||
#define PCI_TYPE (PCI_USES_MEM | PCI_ADDR0 | PCI_NO_ACPI_WAKE)
|
||||
#define PCI_ACX100_REGION1 0x01
|
||||
#define PCI_ACX100_REGION1_SIZE 0x1000 /* Memory size - 4K bytes */
|
||||
@@ -102,7 +107,7 @@
|
||||
#define PCI_POWER_ERROR -1
|
||||
#endif
|
||||
|
||||
-
|
||||
+#endif
|
||||
/***********************************************************************
|
||||
*/
|
||||
static void acxpci_i_tx_timeout(struct net_device *ndev);
|
||||
@@ -653,11 +658,11 @@
|
||||
snprintf(filename, sizeof(filename), "tiacx1%02dc%02X",
|
||||
IS_ACX111(adev)*11, adev->radio_type);
|
||||
|
||||
- fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
|
||||
+ fw_image = acx_s_read_fw(adev->bus_dev, filename, &file_size);
|
||||
if (!fw_image) {
|
||||
adev->need_radio_fw = 1;
|
||||
filename[sizeof("tiacx1NN")-1] = '\0';
|
||||
- fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
|
||||
+ fw_image = acx_s_read_fw(adev->bus_dev, filename, &file_size);
|
||||
if (!fw_image) {
|
||||
FN_EXIT1(NOT_OK);
|
||||
return NOT_OK;
|
||||
@@ -716,7 +721,7 @@
|
||||
snprintf(filename, sizeof(filename), "tiacx1%02dr%02X",
|
||||
IS_ACX111(adev)*11,
|
||||
adev->radio_type);
|
||||
- radio_image = acx_s_read_fw(&adev->pdev->dev, filename, &size);
|
||||
+ radio_image = acx_s_read_fw(adev->bus_dev, filename, &size);
|
||||
if (!radio_image) {
|
||||
printk("acx: can't load radio module '%s'\n", filename);
|
||||
goto fail;
|
||||
@@ -933,7 +938,9 @@
|
||||
|
||||
ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
|
||||
if (!ecpu_ctrl) {
|
||||
+#ifdef CONFIG_PCI
|
||||
acxpci_l_reset_mac(adev);
|
||||
+#endif
|
||||
ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
|
||||
}
|
||||
|
||||
@@ -1473,6 +1480,7 @@
|
||||
static void
|
||||
dummy_netdev_init(struct net_device *ndev) {}
|
||||
|
||||
+#ifdef CONFIG_PCI
|
||||
static int __devinit
|
||||
acxpci_e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
@@ -1606,6 +1614,7 @@
|
||||
** just _presume_ that we're under sem (instead of actually taking it): */
|
||||
/* acx_sem_lock(adev); */
|
||||
adev->pdev = pdev;
|
||||
+ adev->bus_dev = &pdev->dev;
|
||||
adev->ndev = ndev;
|
||||
adev->dev_type = DEVTYPE_PCI;
|
||||
adev->chip_type = chip_type;
|
||||
@@ -1956,7 +1965,7 @@
|
||||
return OK;
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
-
|
||||
+#endif /* CONFIG_PCI */
|
||||
|
||||
/***********************************************************************
|
||||
** acxpci_s_up
|
||||
@@ -2051,7 +2060,7 @@
|
||||
/* then wait until interrupts have finished executing on other CPUs */
|
||||
acx_lock(adev, flags);
|
||||
disable_acx_irq(adev);
|
||||
- synchronize_irq(adev->pdev->irq);
|
||||
+ synchronize_irq(adev->irq);
|
||||
acx_unlock(adev, flags);
|
||||
|
||||
/* we really don't want to have an asynchronous tasklet disturb us
|
||||
@@ -3573,9 +3582,8 @@
|
||||
{
|
||||
void *ptr;
|
||||
|
||||
- ptr = dma_alloc_coherent(adev->pdev ? &adev->pdev->dev : NULL,
|
||||
- size, phy, GFP_KERNEL);
|
||||
-
|
||||
+ ptr = dma_alloc_coherent(adev->bus_dev, size, phy, GFP_KERNEL);
|
||||
+
|
||||
if (ptr) {
|
||||
log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
|
||||
msg, (int)size, ptr, (unsigned long long)*phy);
|
||||
@@ -4137,6 +4145,379 @@
|
||||
}
|
||||
|
||||
|
||||
+#ifdef CONFIG_VLYNQ
|
||||
+struct vlynq_reg_config {
|
||||
+ u32 offset;
|
||||
+ u32 value;
|
||||
+};
|
||||
+
|
||||
+struct vlynq_known {
|
||||
+ u32 chip_id;
|
||||
+ char name[32];
|
||||
+ struct vlynq_mapping rx_mapping[4];
|
||||
+ int irq;
|
||||
+ int irq_type;
|
||||
+ int num_regs;
|
||||
+ struct vlynq_reg_config regs[10];
|
||||
+};
|
||||
+
|
||||
+#define CHIP_TNETW1130 0x00000009
|
||||
+#define CHIP_TNETW1350 0x00000029
|
||||
+static struct vlynq_known known_devices[] = {
|
||||
+ {
|
||||
+ .chip_id = CHIP_TNETW1130, .name = "TI TNETW1130",
|
||||
+ .rx_mapping = {
|
||||
+ { .size = 0x22000, .offset = 0xf0000000 },
|
||||
+ { .size = 0x40000, .offset = 0xc0000000 },
|
||||
+ { .size = 0x0, .offset = 0x0 },
|
||||
+ { .size = 0x0, .offset = 0x0 },
|
||||
+ },
|
||||
+ .irq = 0,
|
||||
+ .irq_type = IRQ_TYPE_EDGE_RISING,
|
||||
+ .num_regs = 5,
|
||||
+ .regs = {
|
||||
+ {
|
||||
+ .offset = 0x790,
|
||||
+ .value = (0xd0000000 - PHYS_OFFSET)
|
||||
+ },
|
||||
+ {
|
||||
+ .offset = 0x794,
|
||||
+ .value = (0xd0000000 - PHYS_OFFSET)
|
||||
+ },
|
||||
+ { .offset = 0x740, .value = 0 },
|
||||
+ { .offset = 0x744, .value = 0x00010000 },
|
||||
+ { .offset = 0x764, .value = 0x00010000 },
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
+ .chip_id = CHIP_TNETW1350, .name = "TI TNETW1350",
|
||||
+ .rx_mapping = {
|
||||
+ { .size = 0x100000, .offset = 0x00300000 },
|
||||
+ { .size = 0x80000, .offset = 0x00000000 },
|
||||
+ { .size = 0x0, .offset = 0x0 },
|
||||
+ { .size = 0x0, .offset = 0x0 },
|
||||
+ },
|
||||
+ .irq = 0,
|
||||
+ .irq_type = IRQ_TYPE_EDGE_RISING,
|
||||
+ .num_regs = 5,
|
||||
+ .regs = {
|
||||
+ {
|
||||
+ .offset = 0x790,
|
||||
+ .value = (0x60000000 - PHYS_OFFSET)
|
||||
+ },
|
||||
+ {
|
||||
+ .offset = 0x794,
|
||||
+ .value = (0x60000000 - PHYS_OFFSET)
|
||||
+ },
|
||||
+ { .offset = 0x740, .value = 0 },
|
||||
+ { .offset = 0x744, .value = 0x00010000 },
|
||||
+ { .offset = 0x764, .value = 0x00010000 },
|
||||
+ },
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct vlynq_device_id acx_vlynq_id[] = {
|
||||
+ { CHIP_TNETW1130, vlynq_div_auto, 0 },
|
||||
+ { CHIP_TNETW1350, vlynq_div_auto, 1 },
|
||||
+ { 0, 0, 0 },
|
||||
+};
|
||||
+
|
||||
+static __devinit int vlynq_probe(struct vlynq_device *vdev,
|
||||
+ struct vlynq_device_id *id)
|
||||
+{
|
||||
+ int result = -EIO, i;
|
||||
+ u32 addr;
|
||||
+ acx_device_t *adev = NULL;
|
||||
+ struct net_device *ndev = NULL;
|
||||
+ acx111_ie_configoption_t co;
|
||||
+ struct vlynq_mapping mapping[4] = { { 0, }, };
|
||||
+ struct vlynq_known *match = NULL;
|
||||
+ int err;
|
||||
+
|
||||
+ FN_ENTER;
|
||||
+ result = vlynq_enable_device(vdev);
|
||||
+ if (result)
|
||||
+ return result;
|
||||
+
|
||||
+ match = &known_devices[id->driver_data];
|
||||
+
|
||||
+ if (!match) {
|
||||
+ result = -ENODEV;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ mapping[0].offset = ARCH_PFN_OFFSET << PAGE_SHIFT;
|
||||
+ mapping[0].size = 0x02000000;
|
||||
+ vlynq_set_local_mapping(vdev, vdev->mem_start, mapping);
|
||||
+ vlynq_set_remote_mapping(vdev, 0, match->rx_mapping);
|
||||
+
|
||||
+ set_irq_type(vlynq_virq_to_irq(vdev, match->irq), match->irq_type);
|
||||
+
|
||||
+ addr = (u32)ioremap(vdev->mem_start, 0x1000);
|
||||
+ if (!addr) {
|
||||
+ printk(KERN_ERR "%s: failed to remap io memory\n",
|
||||
+ vdev->dev.bus_id);
|
||||
+ result = -ENXIO;
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < match->num_regs; i++)
|
||||
+ iowrite32(match->regs[i].value,
|
||||
+ (u32 *)(addr + match->regs[i].offset));
|
||||
+
|
||||
+ iounmap((void *)addr);
|
||||
+
|
||||
+ ndev = alloc_netdev(sizeof(*adev), "wlan%d", dummy_netdev_init);
|
||||
+ /* (NB: memsets to 0 entire area) */
|
||||
+ if (!ndev) {
|
||||
+ printk("acx: no memory for netdevice struct\n");
|
||||
+ goto fail_alloc_netdev;
|
||||
+ }
|
||||
+ ether_setup(ndev);
|
||||
+ ndev->open = &acxpci_e_open;
|
||||
+ ndev->stop = &acxpci_e_close;
|
||||
+ ndev->hard_start_xmit = &acx_i_start_xmit;
|
||||
+ ndev->get_stats = &acx_e_get_stats;
|
||||
+#if IW_HANDLER_VERSION <= 5
|
||||
+ ndev->get_wireless_stats = &acx_e_get_wireless_stats;
|
||||
+#endif
|
||||
+ ndev->wireless_handlers = (struct iw_handler_def *)&acx_ioctl_handler_def;
|
||||
+ ndev->set_multicast_list = &acxpci_i_set_multicast_list;
|
||||
+ ndev->tx_timeout = &acxpci_i_tx_timeout;
|
||||
+ ndev->change_mtu = &acx_e_change_mtu;
|
||||
+ ndev->watchdog_timeo = 4 * HZ;
|
||||
+
|
||||
+ adev = ndev2adev(ndev);
|
||||
+
|
||||
+ memset(adev, 0, sizeof(*adev));
|
||||
+ /** Set up our private interface **/
|
||||
+ spin_lock_init(&adev->lock); /* initial state: unlocked */
|
||||
+ /* We do not start with downed sem: we want PARANOID_LOCKING to work */
|
||||
+ sema_init(&adev->sem, 1);
|
||||
+ /* since nobody can see new netdev yet, we can as well
|
||||
+ ** just _presume_ that we're under sem (instead of actually taking it): */
|
||||
+ /* acx_sem_lock(adev); */
|
||||
+ adev->ndev = ndev;
|
||||
+ adev->vdev = vdev;
|
||||
+ adev->bus_dev = &vdev->dev;
|
||||
+ adev->dev_type = DEVTYPE_PCI;
|
||||
+
|
||||
+/** Finished with private interface **/
|
||||
+
|
||||
+ vlynq_set_drvdata(vdev, ndev);
|
||||
+ if (!request_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start, "acx")) {
|
||||
+ printk("acx: cannot reserve VLYNQ memory region\n");
|
||||
+ goto fail_request_mem_region;
|
||||
+ }
|
||||
+ adev->iobase = ioremap(vdev->mem_start, vdev->mem_end - vdev->mem_start);
|
||||
+ if (!adev->iobase) {
|
||||
+ printk("acx: ioremap() FAILED\n");
|
||||
+ goto fail_ioremap;
|
||||
+ }
|
||||
+ adev->iobase2 = adev->iobase + match->rx_mapping[0].size;
|
||||
+ adev->chip_type = CHIPTYPE_ACX111;
|
||||
+ adev->chip_name = match->name;
|
||||
+ adev->io = IO_ACX111;
|
||||
+ ndev->irq = vlynq_virq_to_irq(vdev, match->irq);
|
||||
+ ndev->base_addr = adev->iobase;
|
||||
+
|
||||
+ printk("acx: found %s-based wireless network card at %s, irq:%d, "
|
||||
+ "phymem:0x%x, mem:0x%p\n",
|
||||
+ match->name, vdev->dev.bus_id, ndev->irq,
|
||||
+ vdev->mem_start, adev->iobase);
|
||||
+ log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
|
||||
+
|
||||
+ if (0 == ndev->irq) {
|
||||
+ printk("acx: can't use IRQ 0\n");
|
||||
+ goto fail_irq;
|
||||
+ }
|
||||
+
|
||||
+ /* to find crashes due to weird driver access
|
||||
+ * to unconfigured interface (ifup) */
|
||||
+ adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
|
||||
+#ifdef NONESSENTIAL_FEATURES
|
||||
+ acx_show_card_eeprom_id(adev);
|
||||
+#endif /* NONESSENTIAL_FEATURES */
|
||||
+
|
||||
+#ifdef SET_MODULE_OWNER
|
||||
+ SET_MODULE_OWNER(ndev);
|
||||
+#endif
|
||||
+ SET_NETDEV_DEV(ndev, adev->bus_dev);
|
||||
+
|
||||
+ log(L_IRQ|L_INIT, "using IRQ %d\n", ndev->irq);
|
||||
+
|
||||
+
|
||||
+ /* ok, pci setup is finished, now start initializing the card */
|
||||
+
|
||||
+ /* NB: read_reg() reads may return bogus data before reset_dev(),
|
||||
+ * since the firmware which directly controls large parts of the I/O
|
||||
+ * registers isn't initialized yet.
|
||||
+ * acx100 seems to be more affected than acx111 */
|
||||
+ if (OK != acxpci_s_reset_dev(adev))
|
||||
+ goto fail_reset;
|
||||
+
|
||||
+ if (OK != acx_s_init_mac(adev))
|
||||
+ goto fail_init_mac;
|
||||
+
|
||||
+ acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
|
||||
+/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
|
||||
+ if (OK != acxpci_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
|
||||
+ goto fail_read_eeprom_version;
|
||||
+
|
||||
+ acx_s_parse_configoption(adev, &co);
|
||||
+ acx_s_set_defaults(adev);
|
||||
+ acx_s_get_firmware_version(adev); /* needs to be after acx_s_init_mac() */
|
||||
+ acx_display_hardware_details(adev);
|
||||
+
|
||||
+ /* Register the card, AFTER everything else has been set up,
|
||||
+ * since otherwise an ioctl could step on our feet due to
|
||||
+ * firmware operations happening in parallel or uninitialized data */
|
||||
+
|
||||
+
|
||||
+ acx_proc_register_entries(ndev);
|
||||
+
|
||||
+ /* Now we have our device, so make sure the kernel doesn't try
|
||||
+ * to send packets even though we're not associated to a network yet */
|
||||
+ acx_stop_queue(ndev, "on probe");
|
||||
+ acx_carrier_off(ndev, "on probe");
|
||||
+
|
||||
+ /* after register_netdev() userspace may start working with dev
|
||||
+ * (in particular, on other CPUs), we only need to up the sem */
|
||||
+ /* acx_sem_unlock(adev); */
|
||||
+
|
||||
+ printk("acx " ACX_RELEASE ": net device %s, driver compiled "
|
||||
+ "against wireless extensions %d and Linux %s\n",
|
||||
+ ndev->name, WIRELESS_EXT, UTS_RELEASE);
|
||||
+
|
||||
+ log(L_IRQ | L_INIT, "using IRQ %d\n", ndev->irq);
|
||||
+
|
||||
+/** done with board specific setup **/
|
||||
+ err = register_netdev(ndev);
|
||||
+ if (OK != err) {
|
||||
+ printk("acx: register_netdev() FAILED: %d\n", err);
|
||||
+ goto fail_register_netdev;
|
||||
+ }
|
||||
+
|
||||
+#if CMD_DISCOVERY
|
||||
+ great_inquisitor(adev);
|
||||
+#endif
|
||||
+
|
||||
+ result = OK;
|
||||
+ goto done;
|
||||
+
|
||||
+ /* error paths: undo everything in reverse order... */
|
||||
+
|
||||
+
|
||||
+ acxpci_s_delete_dma_regions(adev);
|
||||
+
|
||||
+ fail_init_mac:
|
||||
+ fail_read_eeprom_version:
|
||||
+ fail_reset:
|
||||
+ free_netdev(ndev);
|
||||
+
|
||||
+ fail_alloc_netdev:
|
||||
+ fail_irq:
|
||||
+
|
||||
+ iounmap(adev->iobase);
|
||||
+ fail_ioremap:
|
||||
+
|
||||
+ release_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start);
|
||||
+ fail_request_mem_region:
|
||||
+ fail_register_netdev:
|
||||
+ fail:
|
||||
+ vlynq_disable_device(vdev);
|
||||
+ done:
|
||||
+ FN_EXIT1(result);
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+static void vlynq_remove(struct vlynq_device *vdev)
|
||||
+{
|
||||
+ struct net_device *ndev = vlynq_get_drvdata(vdev);;
|
||||
+ acx_device_t *adev;
|
||||
+ unsigned long flags;
|
||||
+ FN_ENTER;
|
||||
+
|
||||
+ if (!ndev) {
|
||||
+ log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
|
||||
+ __func__);
|
||||
+ goto end;
|
||||
+ }
|
||||
+
|
||||
+ acx_lock(adev, flags);
|
||||
+ adev = ndev2adev(ndev);
|
||||
+ acx_unlock(adev, flags);
|
||||
+
|
||||
+ /* If device wasn't hot unplugged... */
|
||||
+ if (adev_present(adev)) {
|
||||
+
|
||||
+ acx_sem_lock(adev);
|
||||
+
|
||||
+ /* disable both Tx and Rx to shut radio down properly */
|
||||
+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
|
||||
+ acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
|
||||
+ acx_lock(adev, flags);
|
||||
+ /* disable power LED to save power :-) */
|
||||
+ log(L_INIT, "switching off power LED to save power\n");
|
||||
+ acxpci_l_power_led(adev, 0);
|
||||
+ /* stop our eCPU */
|
||||
+ acx_unlock(adev, flags);
|
||||
+
|
||||
+ acx_sem_unlock(adev);
|
||||
+ }
|
||||
+
|
||||
+ /* unregister the device to not let the kernel
|
||||
+ * (e.g. ioctls) access a half-deconfigured device
|
||||
+ * NB: this will cause acxpci_e_close() to be called,
|
||||
+ * thus we shouldn't call it under sem! */
|
||||
+ log(L_INIT, "removing device %s\n", ndev->name);
|
||||
+ unregister_netdev(ndev);
|
||||
+
|
||||
+ /* unregister_netdev ensures that no references to us left.
|
||||
+ * For paranoid reasons we continue to follow the rules */
|
||||
+ acx_sem_lock(adev);
|
||||
+
|
||||
+
|
||||
+ if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
|
||||
+ acxpci_s_down(ndev);
|
||||
+ CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
|
||||
+ }
|
||||
+
|
||||
+ acx_proc_unregister_entries(ndev);
|
||||
+
|
||||
+ /* finally, clean up PCI bus state */
|
||||
+ acxpci_s_delete_dma_regions(adev);
|
||||
+ if (adev->iobase)
|
||||
+ iounmap(adev->iobase);
|
||||
+ if (adev->iobase2)
|
||||
+ iounmap(adev->iobase2);
|
||||
+ release_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start);
|
||||
+
|
||||
+ /* remove dev registration */
|
||||
+
|
||||
+ acx_sem_unlock(adev);
|
||||
+ vlynq_disable_device(vdev);
|
||||
+
|
||||
+ /* Free netdev (quite late,
|
||||
+ * since otherwise we might get caught off-guard
|
||||
+ * by a netdev timeout handler execution
|
||||
+ * expecting to see a working dev...) */
|
||||
+ free_netdev(ndev);
|
||||
+
|
||||
+ end:
|
||||
+ FN_EXIT0;
|
||||
+}
|
||||
+
|
||||
+static struct vlynq_driver vlynq_acx = {
|
||||
+ .name = "acx_vlynq",
|
||||
+ .id_table = acx_vlynq_id,
|
||||
+ .probe = vlynq_probe,
|
||||
+ .remove = __devexit_p(vlynq_remove),
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
+
|
||||
+#ifdef CONFIG_PCI
|
||||
/***********************************************************************
|
||||
** Data for init_module/cleanup_module
|
||||
*/
|
||||
@@ -4192,7 +4573,7 @@
|
||||
.resume = acxpci_e_resume
|
||||
#endif /* CONFIG_PM */
|
||||
};
|
||||
-
|
||||
+#endif /* CONFIG_PCI */
|
||||
|
||||
/***********************************************************************
|
||||
** acxpci_e_init_module
|
||||
@@ -4202,7 +4583,7 @@
|
||||
int __init
|
||||
acxpci_e_init_module(void)
|
||||
{
|
||||
- int res;
|
||||
+ int res = 0;
|
||||
|
||||
FN_ENTER;
|
||||
|
||||
@@ -4222,11 +4603,15 @@
|
||||
#endif
|
||||
log(L_INIT,
|
||||
"acx: " ENDIANNESS_STRING
|
||||
- "acx: PCI module " ACX_RELEASE " initialized, "
|
||||
+ "acx: PCI/VLYNQ module " ACX_RELEASE " initialized, "
|
||||
"waiting for cards to probe...\n"
|
||||
);
|
||||
-
|
||||
+#ifdef CONFIG_PCI
|
||||
res = pci_register_driver(&acxpci_drv_id);
|
||||
+#endif
|
||||
+#ifdef CONFIG_VLYNQ
|
||||
+ res = vlynq_register_driver(&vlynq_acx);
|
||||
+#endif
|
||||
FN_EXIT1(res);
|
||||
return res;
|
||||
}
|
||||
@@ -4242,8 +4627,13 @@
|
||||
acxpci_e_cleanup_module(void)
|
||||
{
|
||||
FN_ENTER;
|
||||
+#ifdef CONFIG_VLYNQ
|
||||
+ vlynq_unregister_driver(&vlynq_acx);
|
||||
+#endif
|
||||
|
||||
+#ifdef CONFIG_PCI
|
||||
pci_unregister_driver(&acxpci_drv_id);
|
||||
+#endif
|
||||
|
||||
FN_EXIT0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user