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