1 diff -Nru 1/acx_struct.h 2/acx_struct.h
2 --- 1/acx_struct.h 2007-10-03 23:42:39.000000000 +0800
3 +++ 2/acx_struct.h 2007-10-06 01:15:32.000000000 +0800
6 const u16 *io; /* points to ACX100 or ACX111 PCI I/O register address set */
12 + struct vlynq_device *vdev;
14 + struct device *bus_dev;
16 unsigned long membase;
17 unsigned long membase2;
18 diff -Nru 1/pci.c 2/pci.c
19 --- 1/pci.c 2007-10-03 23:42:39.000000000 +0800
20 +++ 2/pci.c 2007-10-06 01:15:32.000000000 +0800
22 #include <linux/ethtool.h>
23 #include <linux/dma-mapping.h>
24 #include <linux/workqueue.h>
26 +#include <linux/vlynq.h>
31 /***********************************************************************
34 #define PCI_TYPE (PCI_USES_MEM | PCI_ADDR0 | PCI_NO_ACPI_WAKE)
35 #define PCI_ACX100_REGION1 0x01
36 #define PCI_ACX100_REGION1_SIZE 0x1000 /* Memory size - 4K bytes */
39 #define PCI_POWER_ERROR -1
42 +#endif /* CONFIG_PCI */
43 /***********************************************************************
47 static void acxpci_s_up(struct ieee80211_hw *hw);
48 static void acxpci_s_down(struct ieee80211_hw *hw);
50 -void acxpci_put_devname(acx_device_t *adev, struct ethtool_drvinfo *info)
53 - strncpy(info->bus_info,pci_name(adev->pdev), ETHTOOL_BUSINFO_LEN);
56 /***********************************************************************
60 snprintf(filename, sizeof(filename), "tiacx1%02dc%02X",
61 IS_ACX111(adev) * 11, adev->radio_type);
63 - fw_image = acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
64 + fw_image = acx_s_read_fw(adev->bus_dev, filename, &file_size);
66 adev->need_radio_fw = 1;
67 filename[sizeof("tiacx1NN") - 1] = '\0';
69 - acx_s_read_fw(&adev->pdev->dev, filename, &file_size);
70 + acx_s_read_fw(adev->bus_dev, filename, &file_size);
76 snprintf(filename, sizeof(filename), "tiacx1%02dr%02X",
77 IS_ACX111(adev) * 11, adev->radio_type);
78 - radio_image = acx_s_read_fw(&adev->pdev->dev, filename, &size);
79 + radio_image = acx_s_read_fw(adev->bus_dev, filename, &size);
81 printk("acx: can't load radio module '%s'\n", filename);
85 acx_lock(adev, flags);
88 acxpci_l_reset_mac(adev);
91 ecpu_ctrl = read_reg16(adev, IO_ACX_ECPU_CTRL) & 1;
99 acxpci_e_probe(struct pci_dev *pdev, const struct pci_device_id *id)
101 @@ -1477,6 +1478,7 @@
102 /* acx_sem_lock(adev); */
105 + adev->bus_dev = &pdev->dev;
106 adev->dev_type = DEVTYPE_PCI;
108 /** Finished with private interface **/
109 @@ -1916,7 +1918,7 @@
112 #endif /* CONFIG_PM */
114 +#endif /* CONFIG_PCI */
116 /***********************************************************************
118 @@ -1998,7 +2000,7 @@
119 /* then wait until interrupts have finished executing on other CPUs */
120 acx_lock(adev, flags);
121 disable_acx_irq(adev);
122 - synchronize_irq(adev->pdev->irq);
123 + synchronize_irq(adev->irq);
124 acx_unlock(adev, flags);
126 /* we really don't want to have an asynchronous tasklet disturb us
127 @@ -3449,8 +3451,7 @@
131 - ptr = dma_alloc_coherent(adev->pdev ? &adev->pdev->dev : NULL,
132 - size, phy, GFP_KERNEL);
133 + ptr = dma_alloc_coherent(adev->bus_dev, size, phy, GFP_KERNEL);
136 log(L_DEBUG, "%s sz=%d adr=0x%p phy=0x%08llx\n",
137 @@ -4016,10 +4017,370 @@
142 +struct vlynq_reg_config {
147 +struct vlynq_known {
150 + struct vlynq_mapping rx_mapping[4];
154 + struct vlynq_reg_config regs[10];
157 +#define CHIP_TNETW1130 0x00000009
158 +#define CHIP_TNETW1350 0x00000029
160 +static struct vlynq_known known_devices[] = {
162 + .chip_id = CHIP_TNETW1130, .name = "TI TNETW1130",
164 + { .size = 0x22000, .offset = 0xf0000000 },
165 + { .size = 0x40000, .offset = 0xc0000000 },
166 + { .size = 0x0, .offset = 0x0 },
167 + { .size = 0x0, .offset = 0x0 },
170 + .irq_type = IRQ_TYPE_EDGE_RISING,
175 + .value = (0xd0000000 - PHYS_OFFSET)
179 + .value = (0xd0000000 - PHYS_OFFSET)
181 + { .offset = 0x740, .value = 0 },
182 + { .offset = 0x744, .value = 0x00010000 },
183 + { .offset = 0x764, .value = 0x00010000 },
187 + .chip_id = CHIP_TNETW1350, .name = "TI TNETW1350",
189 + { .size = 0x100000, .offset = 0x00300000 },
190 + { .size = 0x80000, .offset = 0x00000000 },
191 + { .size = 0x0, .offset = 0x0 },
192 + { .size = 0x0, .offset = 0x0 },
195 + .irq_type = IRQ_TYPE_EDGE_RISING,
200 + .value = (0x60000000 - PHYS_OFFSET)
204 + .value = (0x60000000 - PHYS_OFFSET)
206 + { .offset = 0x740, .value = 0 },
207 + { .offset = 0x744, .value = 0x00010000 },
208 + { .offset = 0x764, .value = 0x00010000 },
213 +static struct vlynq_device_id acx_vlynq_id[] = {
214 + { CHIP_TNETW1130, vlynq_div_auto, 0 },
215 + { CHIP_TNETW1350, vlynq_div_auto, 1 },
219 +static __devinit int vlynq_probe(struct vlynq_device *vdev,
220 + struct vlynq_device_id *id)
222 + int result = -EIO, i;
224 + struct ieee80211_hw *ieee;
225 + acx_device_t *adev = NULL;
226 + acx111_ie_configoption_t co;
227 + struct vlynq_mapping mapping[4] = { { 0, }, };
228 + struct vlynq_known *match = NULL;
231 + result = vlynq_enable_device(vdev);
235 + match = &known_devices[id->driver_data];
242 + mapping[0].offset = ARCH_PFN_OFFSET << PAGE_SHIFT;
243 + mapping[0].size = 0x02000000;
244 + vlynq_set_local_mapping(vdev, vdev->mem_start, mapping);
245 + vlynq_set_remote_mapping(vdev, 0, match->rx_mapping);
247 + set_irq_type(vlynq_virq_to_irq(vdev, match->irq), match->irq_type);
249 + addr = (u32)ioremap(vdev->mem_start, 0x1000);
251 + printk(KERN_ERR "%s: failed to remap io memory\n",
257 + for (i = 0; i < match->num_regs; i++)
258 + iowrite32(match->regs[i].value,
259 + (u32 *)(addr + match->regs[i].offset));
261 + iounmap((void *)addr);
263 + ieee = ieee80211_alloc_hw(sizeof(struct acx_device), &acxpci_hw_ops);
265 + printk("acx: could not allocate ieee80211 structure %s\n",
267 + goto fail_alloc_netdev;
269 + ieee->flags &= (~IEEE80211_HW_RX_INCLUDES_FCS &
270 + ~IEEE80211_HW_MONITOR_DURING_OPER) |
271 + IEEE80211_HW_WEP_INCLUDE_IV;
274 + adev = ieee2adev(ieee);
276 + memset(adev, 0, sizeof(*adev));
277 + /** Set up our private interface **/
278 + spin_lock_init(&adev->lock); /* initial state: unlocked */
279 + /* We do not start with downed sem: we want PARANOID_LOCKING to work */
280 + mutex_init(&adev->mutex);
281 + /* since nobody can see new netdev yet, we can as well
282 + ** just _presume_ that we're under sem (instead of actually taking it): */
283 + /* acx_sem_lock(adev); */
286 + adev->bus_dev = &vdev->dev;
287 + adev->dev_type = DEVTYPE_PCI;
289 +/** Finished with private interface **/
291 + vlynq_set_drvdata(vdev, ieee);
292 + if (!request_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start, "acx")) {
293 + printk("acx: cannot reserve VLYNQ memory region\n");
294 + goto fail_request_mem_region;
296 + adev->iobase = ioremap(vdev->mem_start, vdev->mem_end - vdev->mem_start);
297 + if (!adev->iobase) {
298 + printk("acx: ioremap() FAILED\n");
301 + adev->iobase2 = adev->iobase + match->rx_mapping[0].size;
302 + adev->chip_type = CHIPTYPE_ACX111;
303 + adev->chip_name = match->name;
304 + adev->io = IO_ACX111;
305 + adev->irq = vlynq_virq_to_irq(vdev, match->irq);
307 + printk("acx: found %s-based wireless network card at %s, irq:%d, "
308 + "phymem:0x%x, mem:0x%p\n",
309 + match->name, vdev->dev.bus_id, adev->irq,
310 + vdev->mem_start, adev->iobase);
311 + log(L_ANY, "initial debug setting is 0x%04X\n", acx_debug);
313 + if (0 == adev->irq) {
314 + printk("acx: can't use IRQ 0\n");
317 + SET_IEEE80211_DEV(ieee, &vdev->dev);
320 + /* to find crashes due to weird driver access
321 + * to unconfigured interface (ifup) */
322 + adev->mgmt_timer.function = (void (*)(unsigned long))0x0000dead;
325 + /* ok, pci setup is finished, now start initializing the card */
327 + /* NB: read_reg() reads may return bogus data before reset_dev(),
328 + * since the firmware which directly controls large parts of the I/O
329 + * registers isn't initialized yet.
330 + * acx100 seems to be more affected than acx111 */
331 + if (OK != acxpci_s_reset_dev(adev))
334 + if (OK != acx_s_init_mac(adev))
335 + goto fail_init_mac;
337 + acx_s_interrogate(adev, &co, ACX111_IE_CONFIG_OPTIONS);
338 +/* TODO: merge them into one function, they are called just once and are the same for pci & usb */
339 + if (OK != acxpci_read_eeprom_byte(adev, 0x05, &adev->eeprom_version))
340 + goto fail_read_eeprom_version;
342 + acx_s_parse_configoption(adev, &co);
343 + acx_s_set_defaults(adev);
344 + acx_s_get_firmware_version(adev); /* needs to be after acx_s_init_mac() */
345 + acx_display_hardware_details(adev);
347 + /* Register the card, AFTER everything else has been set up,
348 + * since otherwise an ioctl could step on our feet due to
349 + * firmware operations happening in parallel or uninitialized data */
352 + acx_proc_register_entries(ieee);
354 + /* Now we have our device, so make sure the kernel doesn't try
355 + * to send packets even though we're not associated to a network yet */
357 + /* after register_netdev() userspace may start working with dev
358 + * (in particular, on other CPUs), we only need to up the sem */
359 + /* acx_sem_unlock(adev); */
361 + printk("acx " ACX_RELEASE ": net device %s, driver compiled "
362 + "against wireless extensions %d and Linux %s\n",
363 + wiphy_name(adev->ieee->wiphy), WIRELESS_EXT, UTS_RELEASE);
365 + MAC_COPY(adev->ieee->wiphy->perm_addr, adev->dev_addr);
367 + log(L_IRQ | L_INIT, "using IRQ %d\n", adev->irq);
369 +/** done with board specific setup **/
371 + acx_init_task_scheduler(adev);
372 + result = ieee80211_register_hw(adev->ieee);
373 + if (OK != result) {
374 + printk("acx: ieee80211_register_hw() FAILED: %d\n", result);
375 + goto fail_register_netdev;
378 + great_inquisitor(adev);
384 + /* error paths: undo everything in reverse order... */
387 + acxpci_s_delete_dma_regions(adev);
390 + fail_read_eeprom_version:
396 + iounmap(adev->iobase);
399 + release_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start);
400 + fail_request_mem_region:
401 + fail_register_netdev:
402 + ieee80211_free_hw(ieee);
404 + vlynq_disable_device(vdev);
410 +static void vlynq_remove(struct vlynq_device *vdev)
412 + struct ieee80211_hw *hw = vlynq_get_drvdata(vdev);
413 + acx_device_t *adev = ieee2adev(hw);
414 + unsigned long flags;
418 + log(L_DEBUG, "%s: card is unused. Skipping any release code\n",
424 + acx_lock(adev, flags);
425 + acx_unlock(adev, flags);
426 + adev->initialized = 0;
428 + /* If device wasn't hot unplugged... */
429 + if (adev_present(adev)) {
431 + acx_sem_lock(adev);
433 + /* disable both Tx and Rx to shut radio down properly */
434 + if (adev->initialized) {
435 + acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_TX, NULL, 0);
436 + acx_s_issue_cmd(adev, ACX1xx_CMD_DISABLE_RX, NULL, 0);
438 + acx_lock(adev, flags);
439 + /* disable power LED to save power :-) */
440 + log(L_INIT, "switching off power LED to save power\n");
441 + acxpci_l_power_led(adev, 0);
442 + /* stop our eCPU */
443 + acx_unlock(adev, flags);
445 + acx_sem_unlock(adev);
448 + /* unregister the device to not let the kernel
449 + * (e.g. ioctls) access a half-deconfigured device
450 + * NB: this will cause acxpci_e_close() to be called,
451 + * thus we shouldn't call it under sem!
452 + * Well, netdev did, but ieee80211 stack does not, so we
453 + * have to do so manually...
455 + acxpci_e_close(hw);
456 + log(L_INIT, "removing device %s\n", wiphy_name(adev->ieee->wiphy));
457 + ieee80211_unregister_hw(adev->ieee);
459 + /* unregister_netdev ensures that no references to us left.
460 + * For paranoid reasons we continue to follow the rules */
461 + acx_sem_lock(adev);
463 + if (adev->dev_state_mask & ACX_STATE_IFACE_UP) {
465 + CLEAR_BIT(adev->dev_state_mask, ACX_STATE_IFACE_UP);
468 + acx_proc_unregister_entries(adev->ieee);
470 + /* finally, clean up PCI bus state */
471 + acxpci_s_delete_dma_regions(adev);
473 + iounmap(adev->iobase);
475 + iounmap(adev->iobase2);
476 + release_mem_region(vdev->mem_start, vdev->mem_end - vdev->mem_start);
478 + /* remove dev registration */
480 + acx_sem_unlock(adev);
481 + vlynq_disable_device(vdev);
483 + /* Free netdev (quite late,
484 + * since otherwise we might get caught off-guard
485 + * by a netdev timeout handler execution
486 + * expecting to see a working dev...) */
487 + ieee80211_free_hw(adev->ieee);
493 +static struct vlynq_driver vlynq_acx = {
494 + .name = "acx_vlynq",
495 + .id_table = acx_vlynq_id,
496 + .probe = vlynq_probe,
497 + .remove = __devexit_p(vlynq_remove),
501 /***********************************************************************
502 ** Data for init_module/cleanup_module
505 static const struct pci_device_id acxpci_id_tbl[] __devinitdata = {
507 .vendor = PCI_VENDOR_ID_TI,
508 @@ -4071,7 +4432,7 @@
509 .resume = acxpci_e_resume
510 #endif /* CONFIG_PM */
513 +#endif /* CONFIG_PCI */
515 /***********************************************************************
516 ** acxpci_e_init_module
517 @@ -4080,7 +4441,7 @@
519 int __init acxpci_e_init_module(void)
526 @@ -4100,10 +4461,15 @@
529 "acx: " ENDIANNESS_STRING
530 - "acx: PCI module " ACX_RELEASE " initialized, "
531 + "acx: PCI/VLYNQ module " ACX_RELEASE " initialized, "
532 "waiting for cards to probe...\n");
535 res = pci_register_driver(&acxpci_drv_id);
538 + res = vlynq_register_driver(&vlynq_acx);
543 @@ -4119,7 +4485,12 @@
548 + vlynq_unregister_driver(&vlynq_acx);
551 pci_unregister_driver(&acxpci_drv_id);