Linux-2.6.12-rc2
[deliverable/linux.git] / drivers / net / pcmcia / ibmtr_cs.c
1 /*======================================================================
2
3 A PCMCIA token-ring driver for IBM-based cards
4
5 This driver supports the IBM PCMCIA Token-Ring Card.
6 Written by Steve Kipisz, kipisz@vnet.ibm.com or
7 bungy@ibm.net
8
9 Written 1995,1996.
10
11 This code is based on pcnet_cs.c from David Hinds.
12
13 V2.2.0 February 1999 - Mike Phillips phillim@amtrak.com
14
15 Linux V2.2.x presented significant changes to the underlying
16 ibmtr.c code. Mainly the code became a lot more organized and
17 modular.
18
19 This caused the old PCMCIA Token Ring driver to give up and go
20 home early. Instead of just patching the old code to make it
21 work, the PCMCIA code has been streamlined, updated and possibly
22 improved.
23
24 This code now only contains code required for the Card Services.
25 All we do here is set the card up enough so that the real ibmtr.c
26 driver can find it and work with it properly.
27
28 i.e. We set up the io port, irq, mmio memory and shared ram
29 memory. This enables ibmtr_probe in ibmtr.c to find the card and
30 configure it as though it was a normal ISA and/or PnP card.
31
32 CHANGES
33
34 v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com)
35 Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c
36
37 v2.2.7 May 1999 Mike Phillips (phillim@amtrak.com)
38 Updated to version 2.2.7 to match the first version of the kernel
39 that the modification to ibmtr.c were incorporated into.
40
41 v2.2.17 July 2000 Burt Silverman (burts@us.ibm.com)
42 Address translation feature of PCMCIA controller is usable so
43 memory windows can be placed in High memory (meaning above
44 0xFFFFF.)
45
46 ======================================================================*/
47
48 #include <linux/kernel.h>
49 #include <linux/init.h>
50 #include <linux/ptrace.h>
51 #include <linux/slab.h>
52 #include <linux/string.h>
53 #include <linux/timer.h>
54 #include <linux/module.h>
55 #include <linux/ethtool.h>
56 #include <linux/netdevice.h>
57 #include <linux/trdevice.h>
58 #include <linux/ibmtr.h>
59
60 #include <pcmcia/version.h>
61 #include <pcmcia/cs_types.h>
62 #include <pcmcia/cs.h>
63 #include <pcmcia/cistpl.h>
64 #include <pcmcia/ds.h>
65
66 #include <asm/uaccess.h>
67 #include <asm/io.h>
68 #include <asm/system.h>
69
70 #define PCMCIA
71 #include "../tokenring/ibmtr.c"
72
73 #ifdef PCMCIA_DEBUG
74 static int pc_debug = PCMCIA_DEBUG;
75 module_param(pc_debug, int, 0);
76 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
77 static char *version =
78 "ibmtr_cs.c 1.10 1996/01/06 05:19:00 (Steve Kipisz)\n"
79 " 2.2.7 1999/05/03 12:00:00 (Mike Phillips)\n"
80 " 2.4.2 2001/30/28 Midnight (Burt Silverman)\n";
81 #else
82 #define DEBUG(n, args...)
83 #endif
84
85 /*====================================================================*/
86
87 /* Parameters that can be set with 'insmod' */
88
89 /* MMIO base address */
90 static u_long mmiobase = 0xce000;
91
92 /* SRAM base address */
93 static u_long srambase = 0xd0000;
94
95 /* SRAM size 8,16,32,64 */
96 static u_long sramsize = 64;
97
98 /* Ringspeed 4,16 */
99 static int ringspeed = 16;
100
101 module_param(mmiobase, ulong, 0);
102 module_param(srambase, ulong, 0);
103 module_param(sramsize, ulong, 0);
104 module_param(ringspeed, int, 0);
105 MODULE_LICENSE("GPL");
106
107 /*====================================================================*/
108
109 static void ibmtr_config(dev_link_t *link);
110 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase);
111 static void ibmtr_release(dev_link_t *link);
112 static int ibmtr_event(event_t event, int priority,
113 event_callback_args_t *args);
114
115 static dev_info_t dev_info = "ibmtr_cs";
116
117 static dev_link_t *ibmtr_attach(void);
118 static void ibmtr_detach(dev_link_t *);
119
120 static dev_link_t *dev_list;
121
122 extern int ibmtr_probe_card(struct net_device *dev);
123 extern irqreturn_t tok_interrupt (int irq, void *dev_id, struct pt_regs *regs);
124
125 /*====================================================================*/
126
127 typedef struct ibmtr_dev_t {
128 dev_link_t link;
129 struct net_device *dev;
130 dev_node_t node;
131 window_handle_t sram_win_handle;
132 struct tok_info *ti;
133 } ibmtr_dev_t;
134
135 static void netdev_get_drvinfo(struct net_device *dev,
136 struct ethtool_drvinfo *info)
137 {
138 strcpy(info->driver, "ibmtr_cs");
139 }
140
141 static struct ethtool_ops netdev_ethtool_ops = {
142 .get_drvinfo = netdev_get_drvinfo,
143 };
144
145 /*======================================================================
146
147 ibmtr_attach() creates an "instance" of the driver, allocating
148 local data structures for one device. The device is registered
149 with Card Services.
150
151 ======================================================================*/
152
153 static dev_link_t *ibmtr_attach(void)
154 {
155 ibmtr_dev_t *info;
156 dev_link_t *link;
157 struct net_device *dev;
158 client_reg_t client_reg;
159 int ret;
160
161 DEBUG(0, "ibmtr_attach()\n");
162
163 /* Create new token-ring device */
164 info = kmalloc(sizeof(*info), GFP_KERNEL);
165 if (!info) return NULL;
166 memset(info,0,sizeof(*info));
167 dev = alloc_trdev(sizeof(struct tok_info));
168 if (!dev) {
169 kfree(info);
170 return NULL;
171 }
172
173 link = &info->link;
174 link->priv = info;
175 info->ti = netdev_priv(dev);
176
177 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
178 link->io.NumPorts1 = 4;
179 link->io.IOAddrLines = 16;
180 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
181 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
182 link->irq.Handler = &tok_interrupt;
183 link->conf.Attributes = CONF_ENABLE_IRQ;
184 link->conf.Vcc = 50;
185 link->conf.IntType = INT_MEMORY_AND_IO;
186 link->conf.Present = PRESENT_OPTION;
187
188 link->irq.Instance = info->dev = dev;
189
190 SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops);
191
192 /* Register with Card Services */
193 link->next = dev_list;
194 dev_list = link;
195 client_reg.dev_info = &dev_info;
196 client_reg.EventMask =
197 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
198 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
199 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
200 client_reg.event_handler = &ibmtr_event;
201 client_reg.Version = 0x0210;
202 client_reg.event_callback_args.client_data = link;
203 ret = pcmcia_register_client(&link->handle, &client_reg);
204 if (ret != 0) {
205 cs_error(link->handle, RegisterClient, ret);
206 goto out_detach;
207 }
208
209 out:
210 return link;
211
212 out_detach:
213 ibmtr_detach(link);
214 link = NULL;
215 goto out;
216 } /* ibmtr_attach */
217
218 /*======================================================================
219
220 This deletes a driver "instance". The device is de-registered
221 with Card Services. If it has been released, all local data
222 structures are freed. Otherwise, the structures will be freed
223 when the device is released.
224
225 ======================================================================*/
226
227 static void ibmtr_detach(dev_link_t *link)
228 {
229 struct ibmtr_dev_t *info = link->priv;
230 dev_link_t **linkp;
231 struct net_device *dev;
232
233 DEBUG(0, "ibmtr_detach(0x%p)\n", link);
234
235 /* Locate device structure */
236 for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
237 if (*linkp == link) break;
238 if (*linkp == NULL)
239 return;
240
241 dev = info->dev;
242
243 if (link->dev)
244 unregister_netdev(dev);
245
246 {
247 struct tok_info *ti = netdev_priv(dev);
248 del_timer_sync(&(ti->tr_timer));
249 }
250 if (link->state & DEV_CONFIG)
251 ibmtr_release(link);
252
253 if (link->handle)
254 pcmcia_deregister_client(link->handle);
255
256 /* Unlink device structure, free bits */
257 *linkp = link->next;
258 free_netdev(dev);
259 kfree(info);
260 } /* ibmtr_detach */
261
262 /*======================================================================
263
264 ibmtr_config() is scheduled to run after a CARD_INSERTION event
265 is received, to configure the PCMCIA socket, and to make the
266 token-ring device available to the system.
267
268 ======================================================================*/
269
270 #define CS_CHECK(fn, ret) \
271 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
272
273 static void ibmtr_config(dev_link_t *link)
274 {
275 client_handle_t handle = link->handle;
276 ibmtr_dev_t *info = link->priv;
277 struct net_device *dev = info->dev;
278 struct tok_info *ti = netdev_priv(dev);
279 tuple_t tuple;
280 cisparse_t parse;
281 win_req_t req;
282 memreq_t mem;
283 int i, last_ret, last_fn;
284 u_char buf[64];
285
286 DEBUG(0, "ibmtr_config(0x%p)\n", link);
287
288 tuple.Attributes = 0;
289 tuple.TupleData = buf;
290 tuple.TupleDataMax = 64;
291 tuple.TupleOffset = 0;
292 tuple.DesiredTuple = CISTPL_CONFIG;
293 CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
294 CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
295 CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
296 link->conf.ConfigBase = parse.config.base;
297
298 /* Configure card */
299 link->state |= DEV_CONFIG;
300
301 link->conf.ConfigIndex = 0x61;
302
303 /* Determine if this is PRIMARY or ALTERNATE. */
304
305 /* Try PRIMARY card at 0xA20-0xA23 */
306 link->io.BasePort1 = 0xA20;
307 i = pcmcia_request_io(link->handle, &link->io);
308 if (i != CS_SUCCESS) {
309 /* Couldn't get 0xA20-0xA23. Try ALTERNATE at 0xA24-0xA27. */
310 link->io.BasePort1 = 0xA24;
311 CS_CHECK(RequestIO, pcmcia_request_io(link->handle, &link->io));
312 }
313 dev->base_addr = link->io.BasePort1;
314
315 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
316 dev->irq = link->irq.AssignedIRQ;
317 ti->irq = link->irq.AssignedIRQ;
318 ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
319
320 /* Allocate the MMIO memory window */
321 req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
322 req.Attributes |= WIN_USE_WAIT;
323 req.Base = 0;
324 req.Size = 0x2000;
325 req.AccessSpeed = 250;
326 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &link->win));
327
328 mem.CardOffset = mmiobase;
329 mem.Page = 0;
330 CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem));
331 ti->mmio = ioremap(req.Base, req.Size);
332
333 /* Allocate the SRAM memory window */
334 req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
335 req.Attributes |= WIN_USE_WAIT;
336 req.Base = 0;
337 req.Size = sramsize * 1024;
338 req.AccessSpeed = 250;
339 CS_CHECK(RequestWindow, pcmcia_request_window(&link->handle, &req, &info->sram_win_handle));
340
341 mem.CardOffset = srambase;
342 mem.Page = 0;
343 CS_CHECK(MapMemPage, pcmcia_map_mem_page(info->sram_win_handle, &mem));
344
345 ti->sram_base = mem.CardOffset >> 12;
346 ti->sram_virt = ioremap(req.Base, req.Size);
347 ti->sram_phys = req.Base;
348
349 CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
350
351 /* Set up the Token-Ring Controller Configuration Register and
352 turn on the card. Check the "Local Area Network Credit Card
353 Adapters Technical Reference" SC30-3585 for this info. */
354 ibmtr_hw_setup(dev, mmiobase);
355
356 link->dev = &info->node;
357 link->state &= ~DEV_CONFIG_PENDING;
358 SET_NETDEV_DEV(dev, &handle_to_dev(handle));
359
360 i = ibmtr_probe_card(dev);
361 if (i != 0) {
362 printk(KERN_NOTICE "ibmtr_cs: register_netdev() failed\n");
363 link->dev = NULL;
364 goto failed;
365 }
366
367 strcpy(info->node.dev_name, dev->name);
368
369 printk(KERN_INFO "%s: port %#3lx, irq %d,",
370 dev->name, dev->base_addr, dev->irq);
371 printk (" mmio %#5lx,", (u_long)ti->mmio);
372 printk (" sram %#5lx,", (u_long)ti->sram_base << 12);
373 printk ("\n" KERN_INFO " hwaddr=");
374 for (i = 0; i < TR_ALEN; i++)
375 printk("%02X", dev->dev_addr[i]);
376 printk("\n");
377 return;
378
379 cs_failed:
380 cs_error(link->handle, last_fn, last_ret);
381 failed:
382 ibmtr_release(link);
383 } /* ibmtr_config */
384
385 /*======================================================================
386
387 After a card is removed, ibmtr_release() will unregister the net
388 device, and release the PCMCIA configuration. If the device is
389 still open, this will be postponed until it is closed.
390
391 ======================================================================*/
392
393 static void ibmtr_release(dev_link_t *link)
394 {
395 ibmtr_dev_t *info = link->priv;
396 struct net_device *dev = info->dev;
397
398 DEBUG(0, "ibmtr_release(0x%p)\n", link);
399
400 pcmcia_release_configuration(link->handle);
401 pcmcia_release_io(link->handle, &link->io);
402 pcmcia_release_irq(link->handle, &link->irq);
403 if (link->win) {
404 struct tok_info *ti = netdev_priv(dev);
405 iounmap(ti->mmio);
406 pcmcia_release_window(link->win);
407 pcmcia_release_window(info->sram_win_handle);
408 }
409
410 link->state &= ~DEV_CONFIG;
411 }
412
413 /*======================================================================
414
415 The card status event handler. Mostly, this schedules other
416 stuff to run after an event is received. A CARD_REMOVAL event
417 also sets some flags to discourage the net drivers from trying
418 to talk to the card any more.
419
420 ======================================================================*/
421
422 static int ibmtr_event(event_t event, int priority,
423 event_callback_args_t *args)
424 {
425 dev_link_t *link = args->client_data;
426 ibmtr_dev_t *info = link->priv;
427 struct net_device *dev = info->dev;
428
429 DEBUG(1, "ibmtr_event(0x%06x)\n", event);
430
431 switch (event) {
432 case CS_EVENT_CARD_REMOVAL:
433 link->state &= ~DEV_PRESENT;
434 if (link->state & DEV_CONFIG) {
435 /* set flag to bypass normal interrupt code */
436 struct tok_info *priv = netdev_priv(dev);
437 priv->sram_phys |= 1;
438 netif_device_detach(dev);
439 }
440 break;
441 case CS_EVENT_CARD_INSERTION:
442 link->state |= DEV_PRESENT;
443 ibmtr_config(link);
444 break;
445 case CS_EVENT_PM_SUSPEND:
446 link->state |= DEV_SUSPEND;
447 /* Fall through... */
448 case CS_EVENT_RESET_PHYSICAL:
449 if (link->state & DEV_CONFIG) {
450 if (link->open)
451 netif_device_detach(dev);
452 pcmcia_release_configuration(link->handle);
453 }
454 break;
455 case CS_EVENT_PM_RESUME:
456 link->state &= ~DEV_SUSPEND;
457 /* Fall through... */
458 case CS_EVENT_CARD_RESET:
459 if (link->state & DEV_CONFIG) {
460 pcmcia_request_configuration(link->handle, &link->conf);
461 if (link->open) {
462 ibmtr_probe(dev); /* really? */
463 netif_device_attach(dev);
464 }
465 }
466 break;
467 }
468 return 0;
469 } /* ibmtr_event */
470
471 /*====================================================================*/
472
473 static void ibmtr_hw_setup(struct net_device *dev, u_int mmiobase)
474 {
475 int i;
476
477 /* Bizarre IBM behavior, there are 16 bits of information we
478 need to set, but the card only allows us to send 4 bits at a
479 time. For each byte sent to base_addr, bits 7-4 tell the
480 card which part of the 16 bits we are setting, bits 3-0 contain
481 the actual information */
482
483 /* First nibble provides 4 bits of mmio */
484 i = (mmiobase >> 16) & 0x0F;
485 outb(i, dev->base_addr);
486
487 /* Second nibble provides 3 bits of mmio */
488 i = 0x10 | ((mmiobase >> 12) & 0x0E);
489 outb(i, dev->base_addr);
490
491 /* Third nibble, hard-coded values */
492 i = 0x26;
493 outb(i, dev->base_addr);
494
495 /* Fourth nibble sets shared ram page size */
496
497 /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */
498 i = (sramsize >> 4) & 0x07;
499 i = ((i == 4) ? 3 : i) << 2;
500 i |= 0x30;
501
502 if (ringspeed == 16)
503 i |= 2;
504 if (dev->base_addr == 0xA24)
505 i |= 1;
506 outb(i, dev->base_addr);
507
508 /* 0x40 will release the card for use */
509 outb(0x40, dev->base_addr);
510
511 return;
512 }
513
514 static struct pcmcia_driver ibmtr_cs_driver = {
515 .owner = THIS_MODULE,
516 .drv = {
517 .name = "ibmtr_cs",
518 },
519 .attach = ibmtr_attach,
520 .detach = ibmtr_detach,
521 };
522
523 static int __init init_ibmtr_cs(void)
524 {
525 return pcmcia_register_driver(&ibmtr_cs_driver);
526 }
527
528 static void __exit exit_ibmtr_cs(void)
529 {
530 pcmcia_unregister_driver(&ibmtr_cs_driver);
531 BUG_ON(dev_list != NULL);
532 }
533
534 module_init(init_ibmtr_cs);
535 module_exit(exit_ibmtr_cs);
This page took 0.091689 seconds and 6 git commands to generate.