1 #define WLAN_HOSTIF WLAN_PCI
3 #include "prism2mgmt.c"
7 #define PCI_SIZE 0x1000 /* Memory size - 4K bytes */
9 /* ISL3874A 11Mb/s WLAN controller */
10 #define PCIVENDOR_INTERSIL 0x1260UL
11 #define PCIDEVICE_ISL3874 0x3873UL /* [MSM] yeah I know...the ID says
12 3873. Trust me, it's a 3874. */
14 /* Samsung SWL-2210P 11Mb/s WLAN controller (uses ISL3874A) */
15 #define PCIVENDOR_SAMSUNG 0x167dUL
16 #define PCIDEVICE_SWL_2210P 0xa000UL
18 #define PCIVENDOR_NETGEAR 0x1385UL /* for MA311 */
20 /* PCI Class & Sub-Class code, Network-'Other controller' */
21 #define PCI_CLASS_NETWORK_OTHERS 0x280
24 /*----------------------------------------------------------------
27 * Probe routine called when a PCI device w/ matching ID is found.
28 * The ISL3874 implementation uses the following map:
29 * BAR0: Prism2.x registers memory mapped, size=4k
30 * Here's the sequence:
31 * - Allocate the PCI resources.
32 * - Read the PCMCIA attribute memory to make sure we have a WLAN card
34 * - Initialize the netdev and wlan data
35 * - Initialize the MAC
38 * pdev ptr to pci device structure containing info about
40 * id ptr to the device id entry that matched this device.
52 ----------------------------------------------------------------*/
56 const struct pci_device_id
*id
)
60 void __iomem
*mem
= NULL
;
61 wlandevice_t
*wlandev
= NULL
;
66 /* Enable the pci device */
67 if (pci_enable_device(pdev
)) {
68 WLAN_LOG_ERROR("%s: pci_enable_device() failed.\n", dev_info
);
73 /* Figure out our resources */
74 phymem
= pci_resource_start(pdev
, 0);
76 if (!request_mem_region(phymem
, pci_resource_len(pdev
, 0), "Prism2")) {
77 printk(KERN_ERR
"prism2: Cannot reserve PCI memory region\n");
82 mem
= ioremap(phymem
, PCI_SIZE
);
84 WLAN_LOG_ERROR("%s: ioremap() failed.\n", dev_info
);
90 WLAN_LOG_INFO("A Prism2.5 PCI device found, "
91 "phymem:0x%llx, irq:%d, mem:0x%p\n",
92 (unsigned long long)phymem
, pdev
->irq
, mem
);
94 if ((wlandev
= create_wlan()) == NULL
) {
95 WLAN_LOG_ERROR("%s: Memory allocation failure.\n", dev_info
);
101 if ( wlan_setup(wlandev
) != 0 ) {
102 WLAN_LOG_ERROR("%s: wlan_setup() failed.\n", dev_info
);
107 /* Setup netdevice's ability to report resources
108 * Note: the netdevice was allocated by wlan_setup()
110 wlandev
->netdev
->irq
= pdev
->irq
;
111 wlandev
->netdev
->mem_start
= (unsigned long) mem
;
112 wlandev
->netdev
->mem_end
= wlandev
->netdev
->mem_start
+
113 pci_resource_len(pdev
, 0);
115 /* Initialize the hw data */
116 hfa384x_create(hw
, wlandev
->netdev
->irq
, 0, mem
);
117 hw
->wlandev
= wlandev
;
119 /* Register the wlandev, this gets us a name and registers the
122 SET_MODULE_OWNER(wlandev
->netdev
);
123 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
124 SET_NETDEV_DEV(wlandev
->netdev
, &(pdev
->dev
));
126 if ( register_wlandev(wlandev
) != 0 ) {
127 WLAN_LOG_ERROR("%s: register_wlandev() failed.\n", dev_info
);
133 /* TODO: Move this and an irq test into an hfa384x_testif() routine.
135 outw(PRISM2STA_MAGIC
, HFA384x_SWSUPPORT(wlandev
->netdev
->base_addr
));
136 reg
=inw( HFA384x_SWSUPPORT(wlandev
->netdev
->base_addr
));
137 if ( reg
!= PRISM2STA_MAGIC
) {
138 WLAN_LOG_ERROR("MAC register access test failed!\n");
144 /* Do a chip-level reset on the MAC */
145 if (prism2_doreset
) {
146 result
= hfa384x_corereset(hw
,
147 prism2_reset_holdtime
,
148 prism2_reset_settletime
, 0);
151 "%s: hfa384x_corereset() failed.\n",
153 unregister_wlandev(wlandev
);
160 pci_set_drvdata(pdev
, wlandev
);
162 /* Shouldn't actually hook up the IRQ until we
163 * _know_ things are alright. A test routine would help.
165 request_irq(wlandev
->netdev
->irq
, hfa384x_interrupt
,
166 SA_SHIRQ
, wlandev
->name
, wlandev
);
168 wlandev
->msdstate
= WLAN_MSD_HWPRESENT
;
174 pci_set_drvdata(pdev
, NULL
);
175 if (wlandev
) kfree(wlandev
);
177 if (mem
) iounmap(mem
);
178 pci_release_regions(pdev
);
179 pci_disable_device(pdev
);
186 static void __devexit
prism2sta_remove_pci(struct pci_dev
*pdev
)
188 wlandevice_t
*wlandev
;
191 wlandev
= (wlandevice_t
*) pci_get_drvdata(pdev
);
194 p80211netdev_hwremoved(wlandev
);
197 prism2sta_ifstate(wlandev
, P80211ENUM_ifstate_disable
);
200 free_irq(pdev
->irq
, wlandev
);
202 unregister_wlandev(wlandev
);
204 /* free local stuff */
210 iounmap((void __iomem
*)wlandev
->netdev
->mem_start
);
211 wlan_unsetup(wlandev
);
213 pci_release_regions(pdev
);
214 pci_disable_device(pdev
);
215 pci_set_drvdata(pdev
, NULL
);
221 static struct pci_device_id pci_id_tbl
[] = {
223 PCIVENDOR_INTERSIL
, PCIDEVICE_ISL3874
,
224 PCI_ANY_ID
, PCI_ANY_ID
,
226 /* Driver data, we just put the name here */
227 (unsigned long)"Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller"
230 PCIVENDOR_INTERSIL
, 0x3872,
231 PCI_ANY_ID
, PCI_ANY_ID
,
233 /* Driver data, we just put the name here */
234 (unsigned long)"Intersil Prism2.5 ISL3872 11Mb/s WLAN Controller"
237 PCIVENDOR_SAMSUNG
, PCIDEVICE_SWL_2210P
,
238 PCI_ANY_ID
, PCI_ANY_ID
,
240 /* Driver data, we just put the name here */
241 (unsigned long)"Samsung MagicLAN SWL-2210P 11Mb/s WLAN Controller"
243 { /* for NetGear MA311 */
244 PCIVENDOR_NETGEAR
, 0x3872,
245 PCI_ANY_ID
, PCI_ANY_ID
,
247 /* Driver data, we just put the name here */
248 (unsigned long)"Netgear MA311 WLAN Controller"
255 MODULE_DEVICE_TABLE(pci
, pci_id_tbl
);
257 /* Function declared here because of ptr reference below */
258 static int __devinit
prism2sta_probe_pci(struct pci_dev
*pdev
,
259 const struct pci_device_id
*id
);
260 static void __devexit
prism2sta_remove_pci(struct pci_dev
*pdev
);
262 static struct pci_driver prism2_pci_drv_id
= {
263 .name
= "prism2_pci",
264 .id_table
= pci_id_tbl
,
265 .probe
= prism2sta_probe_pci
,
266 .remove
= prism2sta_remove_pci
,
268 .suspend
= prism2sta_suspend_pci
,
269 .resume
= prism2sta_resume_pci
,
275 static int __init
prism2pci_init(void)
277 WLAN_LOG_NOTICE("%s Loaded\n", version
);
278 return pci_module_init(&prism2_pci_drv_id
);
281 static void __exit
prism2pci_cleanup(void)
283 pci_unregister_driver(&prism2_pci_drv_id
);
286 module_init(prism2pci_init
);
287 module_exit(prism2pci_cleanup
);
291 int hfa384x_corereset(hfa384x_t
*hw
, int holdtime
, int settletime
, int genesis
)
294 unsigned long timeout
;
298 /* Assert reset and wait awhile
299 * (note: these delays are _really_ long, but they appear to be
302 hfa384x_setreg(hw
, 0xc5, HFA384x_PCICOR
);
303 timeout
= jiffies
+ HZ
/4;
304 while(time_before(jiffies
, timeout
)) udelay(5);
307 hfa384x_setreg(hw
, genesis
, HFA384x_PCIHCR
);
308 timeout
= jiffies
+ HZ
/4;
309 while(time_before(jiffies
, timeout
)) udelay(5);
312 /* Clear the reset and wait some more
314 hfa384x_setreg(hw
, 0x45, HFA384x_PCICOR
);
315 timeout
= jiffies
+ HZ
/2;
316 while(time_before(jiffies
, timeout
)) udelay(5);
318 /* Wait for f/w to complete initialization (CMD:BUSY == 0)
320 timeout
= jiffies
+ 2*HZ
;
321 reg
= hfa384x_getreg(hw
, HFA384x_CMD
);
322 while ( HFA384x_CMD_ISBUSY(reg
) && time_before( jiffies
, timeout
) ) {
323 reg
= hfa384x_getreg(hw
, HFA384x_CMD
);
326 if (HFA384x_CMD_ISBUSY(reg
)) {
327 WLAN_LOG_WARNING("corereset: Timed out waiting for cmd register.\n");