~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/net/pcmcia/ibmtr_cs.c

Version: ~ [ 2.2.5 ] ~ [ 2.4.1 ] ~ [ 2.4.9 ] ~ [ 2.6.17.10 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 memory.
 29     This enables ibmtr_probe in ibmtr.c to find the card and configure it
 30     as though it was a normal ISA and/or PnP card.
 31 
 32     There is some confusion with the difference between available shared
 33     ram and the amount actually reserved from memory.  ibmtr.c sets up
 34     several offsets depending upon the actual on-board memory, not the
 35     reserved memory.  We need to get around this to allow the cards to 
 36     work with other cards in restricted memory space.  Therefore the 
 37     pcmcia_reality_check function.
 38 
 39     TODO
 40         - Write the suspend / resume functions. 
 41         - Fix Kernel Oops when removing card before ifconfig down
 42 
 43     CHANGES
 44 
 45     v2.2.5 April 1999 Mike Phillips (phillim@amtrak.com)
 46     Obscure bug fix, required changed to ibmtr.c not ibmtr_cs.c
 47     
 48     v2.2.7 May 1999 Mike Phillips (phillim@amtrak.com)
 49     Updated to version 2.2.7 to match the first version of the kernel
 50     that the modification to ibmtr.c were incorporated into.
 51     
 52 ======================================================================*/
 53 
 54 #include <linux/kernel.h>
 55 #include <linux/init.h>
 56 #include <linux/sched.h>
 57 #include <linux/ptrace.h>
 58 #include <linux/malloc.h>
 59 #include <linux/string.h>
 60 #include <linux/timer.h>
 61 #include <linux/delay.h>
 62 #include <linux/module.h>
 63 #include <asm/io.h>
 64 #include <asm/system.h>
 65 
 66 #include <linux/netdevice.h>
 67 #include <linux/trdevice.h>
 68 #include <linux/ibmtr.h>
 69 
 70 #include <pcmcia/version.h>
 71 #include <pcmcia/cs_types.h>
 72 #include <pcmcia/cs.h>
 73 #include <pcmcia/cistpl.h>
 74 #include <pcmcia/ds.h>
 75 
 76 #ifdef PCMCIA_DEBUG
 77 static int pc_debug = PCMCIA_DEBUG;
 78 MODULE_PARM(pc_debug, "i");
 79 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
 80 static char *version =
 81 "ibmtr_cs.c 1.10 1996/01/06 05:19:00 (Steve Kipisz)\n"
 82 "           2.2.7 1999/05/03 12:00:00 (Mike Phillips)\n" ;
 83 #else
 84 #define DEBUG(n, args...)
 85 #endif
 86 
 87 /*====================================================================*/
 88 
 89 /* Parameters that can be set with 'insmod' */
 90 
 91 /* Bit map of interrupts to choose from */
 92 static u_int irq_mask = 0xdeb8;
 93 static int irq_list[4] = { -1 };
 94 
 95 /* MMIO base address */
 96 static u_long mmiobase = 0;
 97 
 98 /* SRAM base address */
 99 static u_long srambase = 0;
100 
101 /* SRAM size 8,16,32,64 */
102 static u_long sramsize = 16;
103 
104 /* Ringspeed 4,16 */
105 static int ringspeed = 16;
106 
107 MODULE_PARM(irq_mask, "i");
108 MODULE_PARM(irq_list, "1-4i");
109 MODULE_PARM(mmiobase, "i");
110 MODULE_PARM(srambase, "i");
111 MODULE_PARM(sramsize, "i");
112 MODULE_PARM(ringspeed, "i");
113 
114 /*====================================================================*/
115 
116 static void ibmtr_config(dev_link_t *link);
117 static void ibmtr_hw_setup(struct net_device *dev);
118 static void ibmtr_release(u_long arg);
119 static int ibmtr_event(event_t event, int priority,
120                        event_callback_args_t *args);
121 
122 static dev_info_t dev_info = "ibmtr_cs";
123 
124 static dev_link_t *ibmtr_attach(void);
125 static void ibmtr_detach(dev_link_t *);
126 
127 static dev_link_t *dev_list = NULL;
128 
129 extern int ibmtr_probe(struct net_device *dev);
130 unsigned char pcmcia_reality_check(unsigned char gss);
131 
132 extern int trdev_init(struct net_device *dev);
133 extern void tok_interrupt(int irq, struct pt_regs *regs);
134 extern int tok_init_card(struct net_device *dev);
135 extern unsigned char get_sram_size(struct tok_info *ti);
136 
137 /*====================================================================*/
138 
139 typedef struct ibmtr_dev_t {
140     dev_link_t          link;
141     struct net_device   *dev; /* Changed for 2.2.0 */
142     dev_node_t          node;
143     window_handle_t     sram_win_handle;
144     struct tok_info     ti;
145 } ibmtr_dev_t;
146 
147 /*======================================================================
148 
149     This bit of code is used to avoid unregistering network devices
150     at inappropriate times.  2.2 and later kernels are fairly picky
151     about when this can happen.
152     
153 ======================================================================*/
154 
155 static void flush_stale_links(void)
156 {
157     dev_link_t *link, *next;
158     for (link = dev_list; link; link = next) {
159         next = link->next;
160         if (link->state & DEV_STALE_LINK)
161             ibmtr_detach(link);
162     }
163 }
164 
165 /*====================================================================*/
166 
167 static void cs_error(client_handle_t handle, int func, int ret)
168 {
169     error_info_t err = { func, ret };
170     CardServices(ReportError, handle, &err);
171 }
172 
173 /*======================================================================
174 
175     ibmtr_attach() creates an "instance" of the driver, allocating
176     local data structures for one device.  The device is registered
177     with Card Services.
178 
179 ======================================================================*/
180 
181 static dev_link_t *ibmtr_attach(void)
182 {
183     ibmtr_dev_t *info;
184     dev_link_t *link;
185     struct net_device *dev;
186     client_reg_t client_reg;
187     int i, ret;
188     
189     DEBUG(0, "ibmtr_attach()\n");
190     flush_stale_links();
191 
192     /* Create new token-ring device */
193     info = kmalloc(sizeof(*info), GFP_KERNEL);
194     if (!info) return NULL;
195     memset(info, 0, sizeof(*info));
196     link = &info->link; link->priv = info;
197 
198     link->release.function = &ibmtr_release;
199     link->release.data = (u_long)link;
200     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
201     link->io.NumPorts1 = 4;
202     link->io.IOAddrLines = 16;
203     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE | IRQ_HANDLE_PRESENT;
204     link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
205     if (irq_list[0] == -1)
206         link->irq.IRQInfo2 = irq_mask;
207     else
208         for (i = 0; i < 4; i++)
209             link->irq.IRQInfo2 |= 1 << irq_list[i];
210     link->irq.Handler = &tok_interrupt;
211     link->conf.Attributes = CONF_ENABLE_IRQ;
212     link->conf.Vcc = 50;
213     link->conf.IntType = INT_MEMORY_AND_IO;
214     link->conf.Present = PRESENT_OPTION;
215 
216     dev = init_trdev(NULL,0);
217     dev->priv = &info->ti;
218     link->irq.Instance = info->dev = dev;
219     
220     if (dev == NULL) {
221         ibmtr_detach(link);
222         return NULL;
223     }
224 
225     dev->init = &ibmtr_probe;
226 
227     /* Register with Card Services */
228     link->next = dev_list;
229     dev_list = link;
230     client_reg.dev_info = &dev_info;
231     client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
232     client_reg.EventMask =
233         CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
234         CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
235         CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
236     client_reg.event_handler = &ibmtr_event;
237     client_reg.Version = 0x0210;
238     client_reg.event_callback_args.client_data = link;
239     ret = CardServices(RegisterClient, &link->handle, &client_reg);
240     if (ret != 0) {
241         cs_error(link->handle, RegisterClient, ret);
242         ibmtr_detach(link);
243         return NULL;
244     }
245 
246     return link;
247 } /* ibmtr_attach */
248 
249 /*======================================================================
250 
251     This deletes a driver "instance".  The device is de-registered
252     with Card Services.  If it has been released, all local data
253     structures are freed.  Otherwise, the structures will be freed
254     when the device is released.
255 
256 ======================================================================*/
257 
258 static void ibmtr_detach(dev_link_t *link)
259 {
260     struct ibmtr_dev_t *info = link->priv;
261     dev_link_t **linkp;
262     struct net_device *dev; 
263 
264     DEBUG(0, "ibmtr_detach(0x%p)\n", link);
265 
266     /* Locate device structure */
267     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
268         if (*linkp == link) break;
269     if (*linkp == NULL)
270         return;
271 
272     dev = info->dev;
273     {
274         struct tok_info *ti = (struct tok_info *)dev->priv;
275         del_timer(&(ti->tr_timer));
276     }
277     del_timer(&link->release);
278     if (link->state & DEV_CONFIG) {
279         ibmtr_release((u_long)link);
280         if (link->state & DEV_STALE_CONFIG) {
281             link->state |= DEV_STALE_LINK;
282             return;
283         }
284     }
285 
286     if (link->handle)
287         CardServices(DeregisterClient, link->handle);
288 
289     /* Unlink device structure, free bits */
290     *linkp = link->next;
291     if (link->dev)
292         unregister_trdev(info->dev);
293     kfree(info);
294 
295 } /* ibmtr_detach */
296 
297 /*======================================================================
298 
299     ibmtr_config() is scheduled to run after a CARD_INSERTION event
300     is received, to configure the PCMCIA socket, and to make the
301     token-ring device available to the system.
302 
303 ======================================================================*/
304 
305 #define CS_CHECK(fn, args...) \
306 while ((last_ret=CardServices(last_fn=(fn), args))!=0) goto cs_failed
307 
308 static void ibmtr_config(dev_link_t *link)
309 {
310     client_handle_t handle = link->handle;
311     ibmtr_dev_t *info = link->priv;
312     struct net_device *dev = info->dev;
313     struct tok_info *ti = dev->priv;
314     tuple_t tuple;
315     cisparse_t parse;
316     win_req_t req;
317     memreq_t mem;
318     int i, last_ret, last_fn;
319     u_char buf[64];
320     unsigned char Shared_Ram_Base;
321 
322     DEBUG(0, "ibmtr_config(0x%p)\n", link);
323 
324     tuple.Attributes = 0;
325     tuple.TupleData = buf;
326     tuple.TupleDataMax = 64;
327     tuple.TupleOffset = 0;
328     tuple.DesiredTuple = CISTPL_CONFIG;
329     CS_CHECK(GetFirstTuple, handle, &tuple);
330     CS_CHECK(GetTupleData, handle, &tuple);
331     CS_CHECK(ParseTuple, handle, &tuple, &parse);
332     link->conf.ConfigBase = parse.config.base;
333 
334     /* Configure card */
335     link->state |= DEV_CONFIG;
336 
337     link->conf.ConfigIndex = 0x61;
338 
339     /* Determine if this is PRIMARY or ALTERNATE. */
340 
341     /* Try PRIMARY card at 0xA20-0xA23 */
342     link->io.BasePort1 = 0xA20;
343     i = CardServices(RequestIO, link->handle, &link->io);
344     if (i == CS_SUCCESS) {
345         memcpy(info->node.dev_name, "tr0\0", 4);
346     } else {
347         /* Couldn't get 0xA20-0xA23.  Try ALTERNATE at 0xA24-0xA27. */
348         link->io.BasePort1 = 0xA24;
349         CS_CHECK(RequestIO, link->handle, &link->io);
350         memcpy(info->node.dev_name, "tr1\0", 4);
351     }
352     dev->base_addr = link->io.BasePort1;
353 
354     CS_CHECK(RequestIRQ, link->handle, &link->irq);
355     dev->irq = link->irq.AssignedIRQ;
356     ti->irq = link->irq.AssignedIRQ;
357     ti->global_int_enable=GLOBAL_INT_ENABLE+((dev->irq==9) ? 2 : dev->irq);
358 
359     /* Allocate the MMIO memory window */
360     req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
361     req.Attributes |= WIN_USE_WAIT|WIN_STRICT_ALIGN;
362     req.Base = mmiobase;
363     req.Size = 0x2000;
364     req.AccessSpeed = 250;
365     link->win = (window_handle_t)link->handle;
366     CS_CHECK(RequestWindow, &link->win, &req);
367 
368     mem.CardOffset = req.Base;
369     mem.Page = 0;
370     CS_CHECK(MapMemPage, link->win, &mem);
371     ti->mmio = (u_long)ioremap(req.Base, req.Size);
372 
373     /* Allocate the SRAM memory window */
374     req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM|WIN_ENABLE;
375     req.Attributes |= WIN_USE_WAIT|WIN_MAP_BELOW_1MB;
376     req.Base = srambase;
377     req.Size = sramsize * 1024;
378     req.AccessSpeed = 250;
379     info->sram_win_handle = (window_handle_t)link->handle;
380     CS_CHECK(RequestWindow, &info->sram_win_handle, &req);
381 
382     mem.CardOffset = req.Base;
383     mem.Page = 0;
384     CS_CHECK(MapMemPage, info->sram_win_handle, &mem);
385     Shared_Ram_Base = req.Base >> 12;
386    
387     ti->sram = 0;
388     ti->sram_base = Shared_Ram_Base;
389     
390     CS_CHECK(RequestConfiguration, link->handle, &link->conf);
391 
392     /*  Set up the Token-Ring Controller Configuration Register and
393         turn on the card.  Check the "Local Area Network Credit Card
394         Adapters Technical Reference"  SC30-3585 for this info.  */
395     ibmtr_hw_setup(dev);
396 
397     i = register_trdev(dev);
398     
399     if (i != 0) {
400         printk(KERN_NOTICE "ibmtr_cs: register_trdev() failed\n");
401         goto failed;
402     }
403 
404     link->dev = &info->node;
405     link->state &= ~DEV_CONFIG_PENDING;
406 
407     printk(KERN_INFO "%s: port %#3lx, irq %d,",
408            dev->name, dev->base_addr, dev->irq);
409     printk (" mmio %#5lx,", (u_long)ti->mmio);
410     printk (" sram %#5lx,", (u_long)ti->sram_base << 12);
411     printk ("\n" KERN_INFO "  hwaddr=");
412     for (i = 0; i < TR_ALEN; i++)
413         printk("%02X", dev->dev_addr[i]);
414     printk("\n");
415     return;
416 
417 cs_failed:
418     cs_error(link->handle, last_fn, last_ret);
419 failed:
420     ibmtr_release((u_long)link);
421 } /* ibmtr_config */
422 
423 /*======================================================================
424 
425     After a card is removed, ibmtr_release() will unregister the net
426     device, and release the PCMCIA configuration.  If the device is
427     still open, this will be postponed until it is closed.
428 
429 ======================================================================*/
430 
431 static void ibmtr_release(u_long arg)
432 {
433     dev_link_t *link = (dev_link_t *)arg;
434     ibmtr_dev_t *info = link->priv;
435     struct net_device *dev = info->dev;
436 
437     DEBUG(0, "ibmtr_release(0x%p)\n", link);
438 
439     if (link->open) {
440         DEBUG(1, "ibmtr_cs: release postponed, '%s' "
441               "still open\n", info->node.dev_name);
442         link->state |= DEV_STALE_CONFIG;
443         return;
444     }
445 
446     CardServices(ReleaseConfiguration, link->handle);
447     CardServices(ReleaseIO, link->handle, &link->io);
448     CardServices(ReleaseIRQ, link->handle, &link->irq);
449     if (link->win) {
450         struct tok_info *ti = dev->priv;
451         iounmap((void *)ti->mmio);
452         CardServices(ReleaseWindow, link->win);
453         CardServices(ReleaseWindow, info->sram_win_handle);
454     }
455 
456     link->state &= ~DEV_CONFIG;
457 
458 } /* ibmtr_release */
459 
460 /*======================================================================
461 
462     The card status event handler.  Mostly, this schedules other
463     stuff to run after an event is received.  A CARD_REMOVAL event
464     also sets some flags to discourage the net drivers from trying
465     to talk to the card any more.
466 
467 ======================================================================*/
468 
469 static int ibmtr_event(event_t event, int priority,
470                        event_callback_args_t *args)
471 {
472     dev_link_t *link = args->client_data;
473     ibmtr_dev_t *info = link->priv;
474     struct net_device *dev = info->dev;
475 
476     DEBUG(1, "ibmtr_event(0x%06x)\n", event);
477     
478     switch (event) {
479     case CS_EVENT_CARD_REMOVAL:
480         link->state &= ~DEV_PRESENT;
481         if (link->state & DEV_CONFIG) {
482             netif_device_detach(dev);
483             mod_timer(&link->release, jiffies + HZ/20);
484         }
485         break;
486     case CS_EVENT_CARD_INSERTION:
487         link->state |= DEV_PRESENT;
488         ibmtr_config(link); 
489         break;
490     case CS_EVENT_PM_SUSPEND:
491         link->state |= DEV_SUSPEND;
492         /* Fall through... */
493     case CS_EVENT_RESET_PHYSICAL:
494         if (link->state & DEV_CONFIG) {
495             if (link->open)
496                 netif_device_detach(dev);
497             CardServices(ReleaseConfiguration, link->handle);
498         }
499         break;
500     case CS_EVENT_PM_RESUME:
501         link->state &= ~DEV_SUSPEND;
502         /* Fall through... */
503     case CS_EVENT_CARD_RESET:
504         if (link->state & DEV_CONFIG) {
505             CardServices(RequestConfiguration, link->handle, &link->conf);
506             if (link->open) {
507                 (dev->init)(dev);
508                 netif_device_attach(dev);
509             }
510         }
511         break;
512     }
513     return 0;
514 } /* ibmtr_event */
515 
516 /*====================================================================*/
517 
518 static void ibmtr_hw_setup(struct net_device *dev)
519 {
520     struct tok_info *ti = dev->priv;
521     int i; 
522 
523     /* Bizarre IBM behavior, there are 16 bits of information we
524        need to set, but the card only allows us to send 4 bits at a 
525        time.  For each byte sent to base_addr, bits 7-4 tell the
526        card which part of the 16 bits we are setting, bits 3-0 contain 
527        the actual information */
528 
529     /* First nibble provides 4 bits of mmio */
530     i = ((int)ti->mmio >> 16) & 0x0F;
531     outb(i, dev->base_addr);
532 
533     /* Second nibble provides 3 bits of mmio */
534     i = 0x10 | (((int)ti->mmio >> 12) & 0x0E);
535     outb(i, dev->base_addr);
536 
537     /* Third nibble, hard-coded values */
538     i = 0x26;
539     outb(i, dev->base_addr);
540 
541     /* Fourth nibble sets shared ram page size */
542 
543     /* 8 = 00, 16 = 01, 32 = 10, 64 = 11 */          
544         
545     i = (sramsize >> 4) & 0x07; 
546     i = ((i == 4) ? 3 : i) << 2;
547     i |= 0x30;
548 
549     if (ringspeed == 16)
550         i |= 2;
551     if (dev->base_addr == 0xA24)
552         i |= 1;
553     outb(i, dev->base_addr);
554 
555     /* X40 will release the card for use */
556 
557     outb(0x40, dev->base_addr);
558     
559     return;
560 }
561 
562 /*======================================================================
563   
564     A sweet little function that circumvents the problem with
565     ibmtr.c trying to use more memory than we can allocate for
566     the PCMCIA card.  ibmtr.c just assumes that if a card has 
567     64K of shared ram, the entire 64K must be mapped into memory,
568     whereas resources are sometimes a little tight in card services
569     so we fool ibmtr.c into thinking the card has less memory on
570     it than it has.
571     
572 ======================================================================*/
573 
574 unsigned char pcmcia_reality_check(unsigned char gss)
575 {
576     return (gss < sramsize) ? sramsize : gss;
577 }
578 
579 /*====================================================================*/
580 
581 static int __init init_ibmtr_cs(void)
582 {
583     servinfo_t serv;
584     DEBUG(0, "%s\n", version);
585     CardServices(GetCardServicesInfo, &serv);
586     if (serv.Revision != CS_RELEASE_CODE) {
587         printk(KERN_NOTICE "ibmtr_cs: Card Services release "
588                "does not match!\n");
589         return -1;
590     }
591     register_pccard_driver(&dev_info, &ibmtr_attach, &ibmtr_detach);
592     return 0;
593 }
594 
595 static void __exit exit_ibmtr_cs(void)
596 {
597     DEBUG(0, "ibmtr_cs: unloading\n");
598     unregister_pccard_driver(&dev_info);
599     while (dev_list != NULL)
600         ibmtr_detach(dev_list);
601 }
602 
603 module_init(init_ibmtr_cs);
604 module_exit(exit_ibmtr_cs);
605 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.