Commit | Line | Data |
---|---|---|
f7c1be0c MB |
1 | /*--------------------------------------------------------------------------- |
2 | FT1000 driver for Flarion Flash OFDM NIC Device | |
3 | ||
4 | Copyright (C) 1999 David A. Hinds. All Rights Reserved. | |
5 | Copyright (C) 2002 Flarion Technologies, All rights reserved. | |
6 | Copyright (C) 2006 Patrik Ostrihon, All rights reserved. | |
7 | Copyright (C) 2006 ProWeb Consulting, a.s, All rights reserved. | |
8 | ||
9 | The initial developer of the original code is David A. Hinds | |
10 | <dahinds@users.sourceforge.net>. Portions created by David A. Hinds. | |
11 | ||
12 | This file was modified to support the Flarion Flash OFDM NIC Device | |
13 | by Wai Chan (w.chan@flarion.com). | |
14 | ||
15 | Port for kernel 2.6 created by Patrik Ostrihon (patrik.ostrihon@pwc.sk) | |
bf3146c8 | 16 | |
f7c1be0c MB |
17 | This program is free software; you can redistribute it and/or modify it |
18 | under the terms of the GNU General Public License as published by the Free | |
19 | Software Foundation; either version 2 of the License, or (at your option) any | |
20 | later version. This program is distributed in the hope that it will be useful, | |
21 | but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
22 | or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
23 | more details. You should have received a copy of the GNU General Public | |
24 | License along with this program; if not, write to the | |
25 | Free Software Foundation, Inc., 59 Temple Place - | |
26 | Suite 330, Boston, MA 02111-1307, USA. | |
27 | -----------------------------------------------------------------------------*/ | |
28 | ||
29 | #include <linux/kernel.h> | |
30 | #include <linux/module.h> | |
31 | #include <linux/init.h> | |
32 | #include <linux/ptrace.h> | |
33 | #include <linux/slab.h> | |
34 | #include <linux/string.h> | |
35 | #include <linux/timer.h> | |
36 | #include <linux/ioport.h> | |
37 | #include <linux/delay.h> | |
38 | ||
39 | #include <linux/netdevice.h> | |
40 | #include <linux/etherdevice.h> | |
41 | ||
42 | //#include <pcmcia/version.h> // Slavius 21.10.2009 removed from kernel | |
43 | #include <pcmcia/cs_types.h> | |
44 | #include <pcmcia/cs.h> | |
45 | #include <pcmcia/cistpl.h> | |
46 | #include <pcmcia/cisreg.h> | |
47 | #include <pcmcia/ds.h> | |
48 | ||
49 | #include <asm/io.h> | |
50 | #include <asm/system.h> | |
51 | #include <asm/byteorder.h> | |
52 | #include <asm/uaccess.h> | |
53 | ||
54 | #include "ft1000_cs.h" // Slavius 21.10.2009 because CS_SUCCESS constant is missing due to removed pcmcia/version.h | |
55 | ||
56 | /*====================================================================*/ | |
57 | ||
58 | /* Module parameters */ | |
59 | ||
60 | #define INT_MODULE_PARM(n, v) static int n = v; MODULE_PARM(n, "i") | |
61 | ||
62 | MODULE_AUTHOR("Wai Chan"); | |
63 | MODULE_DESCRIPTION("FT1000 PCMCIA driver"); | |
64 | MODULE_LICENSE("GPL"); | |
65 | ||
66 | /* Newer, simpler way of listing specific interrupts */ | |
67 | ||
68 | /* The old way: bit map of interrupts to choose from */ | |
69 | /* This means pick from 15, 14, 12, 11, 10, 9, 7, 5, 4, and 3 */ | |
70 | ||
71 | /* | |
72 | All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If | |
73 | you do not define PCMCIA_DEBUG at all, all the debug code will be | |
74 | left out. If you compile with PCMCIA_DEBUG=0, the debug code will | |
75 | be present but disabled. | |
76 | */ | |
77 | #ifdef FT_DEBUG | |
78 | #define DEBUG(n, args...) printk(KERN_DEBUG args) | |
79 | #else | |
80 | #define DEBUG(n, args...) | |
81 | #endif | |
82 | ||
83 | /*====================================================================*/ | |
84 | ||
85 | struct net_device *init_ft1000_card(int, int, unsigned char *, | |
86 | void *ft1000_reset, struct pcmcia_device * link, | |
87 | struct device *fdev); | |
88 | void stop_ft1000_card(struct net_device *); | |
89 | ||
90 | static int ft1000_config(struct pcmcia_device *link); | |
91 | static void ft1000_release(struct pcmcia_device *link); | |
92 | ||
93 | /* | |
94 | The attach() and detach() entry points are used to create and destroy | |
95 | "instances" of the driver, where each instance represents everything | |
96 | needed to manage one actual PCMCIA card. | |
97 | */ | |
98 | ||
99 | static void ft1000_detach(struct pcmcia_device *link); | |
100 | static int ft1000_attach(struct pcmcia_device *link); | |
101 | ||
102 | typedef struct local_info_t { | |
103 | struct pcmcia_device *link; | |
104 | struct net_device *dev; | |
105 | } local_info_t; | |
106 | ||
107 | #define MAX_ASIC_RESET_CNT 10 | |
108 | #define COR_DEFAULT 0x55 | |
109 | ||
110 | /*====================================================================*/ | |
111 | ||
112 | static void ft1000_reset(struct pcmcia_device * link) | |
113 | { | |
114 | conf_reg_t reg; | |
115 | ||
116 | DEBUG(0, "ft1000_cs:ft1000_reset is called................\n"); | |
117 | ||
118 | /* Soft-Reset card */ | |
119 | reg.Action = CS_WRITE; | |
120 | reg.Offset = CISREG_COR; | |
121 | reg.Value = COR_SOFT_RESET; | |
122 | pcmcia_access_configuration_register(link, ®); | |
123 | ||
124 | /* Wait until the card has acknowledged our reset */ | |
125 | udelay(2); | |
126 | ||
127 | /* Restore original COR configuration index */ | |
128 | /* Need at least 2 write to respond */ | |
129 | reg.Action = CS_WRITE; | |
130 | reg.Offset = CISREG_COR; | |
131 | reg.Value = COR_DEFAULT; | |
132 | pcmcia_access_configuration_register(link, ®); | |
133 | ||
134 | /* Wait until the card has finished restarting */ | |
135 | udelay(1); | |
136 | ||
137 | reg.Action = CS_WRITE; | |
138 | reg.Offset = CISREG_COR; | |
139 | reg.Value = COR_DEFAULT; | |
140 | pcmcia_access_configuration_register(link, ®); | |
141 | ||
142 | /* Wait until the card has finished restarting */ | |
143 | udelay(1); | |
144 | ||
145 | reg.Action = CS_WRITE; | |
146 | reg.Offset = CISREG_COR; | |
147 | reg.Value = COR_DEFAULT; | |
148 | pcmcia_access_configuration_register(link, ®); | |
149 | ||
150 | /* Wait until the card has finished restarting */ | |
151 | udelay(1); | |
152 | ||
153 | } | |
154 | ||
155 | /*====================================================================*/ | |
156 | ||
157 | static int get_tuple_first(struct pcmcia_device *link, tuple_t * tuple, | |
158 | cisparse_t * parse) | |
159 | { | |
160 | int i; | |
161 | i = pcmcia_get_first_tuple(link, tuple); | |
162 | if (i != CS_SUCCESS) | |
163 | return i; | |
164 | i = pcmcia_get_tuple_data(link, tuple); | |
165 | if (i != CS_SUCCESS) | |
166 | return i; | |
167 | return pcmcia_parse_tuple(tuple, parse); // Slavius 21.10.2009 removed unused link parameter | |
168 | } | |
169 | ||
170 | static int get_tuple_next(struct pcmcia_device *link, tuple_t * tuple, | |
171 | cisparse_t * parse) | |
172 | { | |
173 | int i; | |
174 | i = pcmcia_get_next_tuple(link, tuple); | |
175 | if (i != CS_SUCCESS) | |
176 | return i; | |
177 | i = pcmcia_get_tuple_data(link, tuple); | |
178 | if (i != CS_SUCCESS) | |
179 | return i; | |
180 | return pcmcia_parse_tuple(tuple, parse); // Slavius 21.10.2009 removed unused link parameter | |
181 | } | |
182 | ||
183 | /*====================================================================== | |
184 | ||
bf3146c8 | 185 | |
f7c1be0c MB |
186 | ======================================================================*/ |
187 | ||
188 | static int ft1000_attach(struct pcmcia_device *link) | |
189 | { | |
190 | ||
191 | local_info_t *local; | |
192 | ||
193 | DEBUG(0, "ft1000_cs: ft1000_attach()\n"); | |
194 | ||
195 | local = kmalloc(sizeof(local_info_t), GFP_KERNEL); | |
196 | if (!local) { | |
197 | return -ENOMEM; | |
198 | } | |
199 | memset(local, 0, sizeof(local_info_t)); | |
200 | local->link = link; | |
201 | ||
202 | link->priv = local; | |
203 | local->dev = NULL; | |
204 | ||
205 | link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; | |
206 | link->irq.IRQInfo1 = IRQ_LEVEL_ID; | |
207 | link->conf.Attributes = CONF_ENABLE_IRQ; | |
208 | link->conf.IntType = INT_MEMORY_AND_IO; | |
209 | link->irq.Handler = NULL; | |
210 | ||
211 | return ft1000_config(link); | |
212 | } /* ft1000_attach */ | |
213 | ||
214 | /*====================================================================== | |
215 | ||
216 | This deletes a driver "instance". The device is de-registered | |
217 | with Card Services. If it has been released, all local data | |
218 | structures are freed. Otherwise, the structures will be freed | |
219 | when the device is released. | |
220 | ||
221 | ======================================================================*/ | |
222 | ||
223 | static void ft1000_detach(struct pcmcia_device *link) | |
224 | { | |
225 | struct net_device *dev = ((local_info_t *) link->priv)->dev; | |
226 | ||
227 | DEBUG(0, "ft1000_cs: ft1000_detach(0x%p)\n", link); | |
228 | ||
229 | if (link == NULL) { | |
230 | DEBUG(0,"ft1000_cs:ft1000_detach: Got a NULL pointer\n"); | |
231 | return; | |
232 | } | |
233 | ||
234 | if (dev) { | |
235 | stop_ft1000_card(dev); | |
236 | } | |
237 | ||
238 | ft1000_release(link); | |
239 | ||
240 | /* This points to the parent local_info_t struct */ | |
241 | free_netdev(dev); | |
242 | ||
243 | } /* ft1000_detach */ | |
244 | ||
245 | /*====================================================================== | |
246 | ||
247 | ft1000_config() is scheduled to run after a CARD_INSERTION event | |
248 | is received, to configure the PCMCIA socket, and to make the | |
249 | device available to the system. | |
bf3146c8 | 250 | |
f7c1be0c MB |
251 | ======================================================================*/ |
252 | ||
253 | #define CS_CHECK(fn, ret) \ | |
254 | do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) | |
255 | ||
256 | #define CFG_CHECK(fn, ret) \ | |
257 | last_fn = (fn); if ((last_ret = (ret)) != 0) goto next_entry | |
258 | ||
259 | static int ft1000_config(struct pcmcia_device * link) | |
260 | { | |
261 | tuple_t tuple; | |
262 | cisparse_t parse; | |
263 | int last_fn, last_ret, i; | |
264 | u_char buf[64]; | |
265 | cistpl_lan_node_id_t *node_id; | |
266 | cistpl_cftable_entry_t dflt = { 0 }; | |
267 | cistpl_cftable_entry_t *cfg; | |
268 | unsigned char mac_address[6]; | |
269 | ||
270 | DEBUG(0, "ft1000_cs: ft1000_config(0x%p)\n", link); | |
271 | ||
272 | /* | |
273 | This reads the card's CONFIG tuple to find its configuration | |
274 | registers. | |
275 | */ | |
276 | // tuple.DesiredTuple = CISTPL_CONFIG; | |
277 | // tuple.Attributes = 0; | |
278 | tuple.TupleData = buf; | |
279 | tuple.TupleDataMax = sizeof(buf); | |
280 | tuple.TupleOffset = 0; | |
281 | // CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | |
282 | // CS_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | |
283 | // CS_CHECK(ParseTuple, pcmcia_parse_tuple(link, &tuple, &parse)); | |
284 | // link->conf.ConfigBase = parse.config.base; | |
285 | // link->conf.Present = parse.config.rmask[0]; | |
286 | ||
287 | /* | |
288 | In this loop, we scan the CIS for configuration table entries, | |
289 | each of which describes a valid card configuration, including | |
290 | voltage, IO window, memory window, and interrupt settings. | |
291 | ||
292 | We make no assumptions about the card to be configured: we use | |
293 | just the information available in the CIS. In an ideal world, | |
294 | this would work for any PCMCIA card, but it requires a complete | |
295 | and accurate CIS. In practice, a driver usually "knows" most of | |
296 | these things without consulting the CIS, and most client drivers | |
297 | will only use the CIS to fill in implementation-defined details. | |
298 | */ | |
299 | tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; | |
300 | tuple.Attributes = 0; | |
301 | CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(link, &tuple)); | |
302 | while (1) { | |
303 | cfg = &(parse.cftable_entry); | |
304 | CFG_CHECK(GetTupleData, pcmcia_get_tuple_data(link, &tuple)); | |
305 | CFG_CHECK(ParseTuple, | |
306 | pcmcia_parse_tuple(&tuple, &parse)); // Slavius 21.10.2009 removed unused link parameter | |
307 | ||
308 | if (cfg->flags & CISTPL_CFTABLE_DEFAULT) | |
309 | dflt = *cfg; | |
310 | if (cfg->index == 0) | |
311 | goto next_entry; | |
312 | link->conf.ConfigIndex = cfg->index; | |
313 | ||
314 | /* Do we need to allocate an interrupt? */ | |
315 | if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1) | |
316 | link->conf.Attributes |= CONF_ENABLE_IRQ; | |
317 | ||
318 | /* IO window settings */ | |
319 | link->io.NumPorts1 = link->io.NumPorts2 = 0; | |
320 | if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) { | |
321 | cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io; | |
322 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; | |
323 | if (!(io->flags & CISTPL_IO_8BIT)) { | |
324 | DEBUG(0, "ft1000_cs: IO_DATA_PATH_WIDTH_16\n"); | |
325 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; | |
326 | } | |
327 | if (!(io->flags & CISTPL_IO_16BIT)) { | |
328 | DEBUG(0, "ft1000_cs: IO_DATA_PATH_WIDTH_8\n"); | |
329 | link->io.Attributes1 = IO_DATA_PATH_WIDTH_8; | |
330 | } | |
331 | link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; | |
332 | link->io.BasePort1 = io->win[0].base; | |
333 | link->io.NumPorts1 = io->win[0].len; | |
334 | if (io->nwin > 1) { | |
335 | link->io.Attributes2 = link->io.Attributes1; | |
336 | link->io.BasePort2 = io->win[1].base; | |
337 | link->io.NumPorts2 = io->win[1].len; | |
338 | } | |
339 | /* This reserves IO space but doesn't actually enable it */ | |
340 | pcmcia_request_io(link, &link->io); | |
341 | } | |
342 | ||
343 | break; | |
344 | ||
345 | next_entry: | |
346 | last_ret = pcmcia_get_next_tuple(link, &tuple); | |
347 | } | |
348 | if (last_ret != CS_SUCCESS) { | |
349 | cs_error(link, RequestIO, last_ret); | |
350 | goto failed; | |
bf3146c8 | 351 | } |
f7c1be0c MB |
352 | |
353 | /* | |
354 | Allocate an interrupt line. Note that this does not assign a | |
355 | handler to the interrupt, unless the 'Handler' member of the | |
356 | irq structure is initialized. | |
357 | */ | |
358 | CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); | |
359 | ||
360 | /* | |
361 | This actually configures the PCMCIA socket -- setting up | |
362 | the I/O windows and the interrupt mapping, and putting the | |
363 | card and host interface into "Memory and IO" mode. | |
364 | */ | |
365 | CS_CHECK(RequestConfiguration, | |
366 | pcmcia_request_configuration(link, &link->conf)); | |
367 | ||
368 | /* Get MAC address from tuples */ | |
369 | ||
370 | tuple.Attributes = tuple.TupleOffset = 0; | |
371 | tuple.TupleData = buf; | |
372 | tuple.TupleDataMax = sizeof(buf); | |
373 | ||
374 | /* Check for a LAN function extension tuple */ | |
375 | tuple.DesiredTuple = CISTPL_FUNCE; | |
376 | i = get_tuple_first(link, &tuple, &parse); | |
377 | while (i == CS_SUCCESS) { | |
378 | if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID) | |
379 | break; | |
380 | i = get_tuple_next(link, &tuple, &parse); | |
381 | } | |
382 | ||
383 | if (i == CS_SUCCESS) { | |
384 | node_id = (cistpl_lan_node_id_t *) parse.funce.data; | |
385 | if (node_id->nb == 6) { | |
386 | for (i = 0; i < 6; i++) | |
387 | mac_address[i] = node_id->id[i]; | |
388 | } | |
389 | } | |
390 | ||
391 | ((local_info_t *) link->priv)->dev = | |
392 | init_ft1000_card(link->irq.AssignedIRQ, link->io.BasePort1, | |
393 | &mac_address[0], ft1000_reset, link, | |
394 | &handle_to_dev(link)); | |
395 | ||
396 | /* | |
397 | At this point, the dev_node_t structure(s) need to be | |
398 | initialized and arranged in a linked list at link->dev. | |
399 | */ | |
400 | ||
401 | /* Finally, report what we've done */ | |
402 | ||
403 | return 0; | |
404 | ||
405 | cs_failed: | |
406 | cs_error(link, last_fn, last_ret); | |
407 | failed: | |
408 | ft1000_release(link); | |
409 | return -ENODEV; | |
410 | ||
411 | } /* ft1000_config */ | |
412 | ||
413 | /*====================================================================== | |
414 | ||
415 | After a card is removed, ft1000_release() will unregister the | |
416 | device, and release the PCMCIA configuration. If the device is | |
417 | still open, this will be postponed until it is closed. | |
bf3146c8 | 418 | |
f7c1be0c MB |
419 | ======================================================================*/ |
420 | ||
421 | static void ft1000_release(struct pcmcia_device * link) | |
422 | { | |
423 | ||
424 | DEBUG(0, "ft1000_cs: ft1000_release(0x%p)\n", link); | |
425 | ||
426 | /* | |
427 | If the device is currently in use, we won't release until it | |
428 | is actually closed, because until then, we can't be sure that | |
429 | no one will try to access the device or its data structures. | |
430 | */ | |
431 | ||
432 | /* Unlink the device chain */ | |
433 | link->dev_node = NULL; | |
434 | ||
435 | /* | |
436 | In a normal driver, additional code may be needed to release | |
bf3146c8 | 437 | other kernel data structures associated with this device. |
f7c1be0c MB |
438 | */ |
439 | ||
440 | /* Don't bother checking to see if these succeed or not */ | |
441 | ||
442 | pcmcia_disable_device(link); | |
443 | } /* ft1000_release */ | |
444 | ||
445 | /*====================================================================== | |
446 | ||
447 | The card status event handler. Mostly, this schedules other | |
448 | stuff to run after an event is received. | |
449 | ||
450 | When a CARD_REMOVAL event is received, we immediately set a | |
451 | private flag to block future accesses to this device. All the | |
452 | functions that actually access the device should check this flag | |
453 | to make sure the card is still present. | |
bf3146c8 | 454 | |
f7c1be0c MB |
455 | ======================================================================*/ |
456 | ||
457 | static int ft1000_suspend(struct pcmcia_device *link) | |
458 | { | |
459 | struct net_device *dev = ((local_info_t *) link->priv)->dev; | |
460 | ||
461 | DEBUG(1, "ft1000_cs: ft1000_event(0x%06x)\n", event); | |
462 | ||
463 | if (link->open) | |
464 | netif_device_detach(dev); | |
465 | return 0; | |
466 | } | |
467 | ||
468 | static int ft1000_resume(struct pcmcia_device *link) | |
469 | { | |
470 | /* struct net_device *dev = link->priv; | |
471 | */ | |
472 | return 0; | |
473 | } | |
474 | ||
475 | ||
476 | ||
477 | /*====================================================================*/ | |
478 | ||
479 | static struct pcmcia_device_id ft1000_ids[] = { | |
480 | PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x0100), | |
481 | PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x1000), | |
482 | PCMCIA_DEVICE_MANF_CARD(0x02cc, 0x1300), | |
483 | PCMCIA_DEVICE_NULL, | |
484 | }; | |
485 | ||
486 | MODULE_DEVICE_TABLE(pcmcia, ft1000_ids); | |
487 | ||
488 | static struct pcmcia_driver ft1000_cs_driver = { | |
489 | .owner = THIS_MODULE, | |
490 | .drv = { | |
491 | .name = "ft1000_cs", | |
492 | }, | |
493 | .probe = ft1000_attach, | |
494 | .remove = ft1000_detach, | |
495 | .id_table = ft1000_ids, | |
496 | .suspend = ft1000_suspend, | |
497 | .resume = ft1000_resume, | |
498 | }; | |
499 | ||
500 | static int __init init_ft1000_cs(void) | |
501 | { | |
502 | DEBUG(0, "ft1000_cs: loading\n"); | |
503 | return pcmcia_register_driver(&ft1000_cs_driver); | |
504 | } | |
505 | ||
506 | static void __exit exit_ft1000_cs(void) | |
507 | { | |
508 | DEBUG(0, "ft1000_cs: unloading\n"); | |
509 | pcmcia_unregister_driver(&ft1000_cs_driver); | |
510 | } | |
511 | ||
512 | module_init(init_ft1000_cs); | |
513 | module_exit(exit_ft1000_cs); |