More meth updates.
[linux-2.6/linux-mips.git] / drivers / net / mac89x0.c
blob67e1489403cfdafaf0c3d9e3b31cc3c447ce049d
1 /* mac89x0.c: A Crystal Semiconductor CS89[02]0 driver for linux. */
2 /*
3 Written 1996 by Russell Nelson, with reference to skeleton.c
4 written 1993-1994 by Donald Becker.
6 This software may be used and distributed according to the terms
7 of the GNU General Public License, incorporated herein by reference.
9 The author may be reached at nelson@crynwr.com, Crynwr
10 Software, 11 Grant St., Potsdam, NY 13676
12 Changelog:
14 Mike Cruse : mcruse@cti-ltd.com
15 : Changes for Linux 2.0 compatibility.
16 : Added dev_id parameter in net_interrupt(),
17 : request_irq() and free_irq(). Just NULL for now.
19 Mike Cruse : Added MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT macros
20 : in net_open() and net_close() so kerneld would know
21 : that the module is in use and wouldn't eject the
22 : driver prematurely.
24 Mike Cruse : Rewrote init_module() and cleanup_module using 8390.c
25 : as an example. Disabled autoprobing in init_module(),
26 : not a good thing to do to other devices while Linux
27 : is running from all accounts.
29 Alan Cox : Removed 1.2 support, added 2.1 extra counters.
31 David Huggins-Daines <dhd@debian.org>
33 Split this off into mac89x0.c, and gutted it of all parts which are
34 not relevant to the existing CS8900 cards on the Macintosh
35 (i.e. basically the Daynaport CS and LC cards). To be precise:
37 * Removed all the media-detection stuff, because these cards are
38 TP-only.
40 * Lobotomized the ISA interrupt bogosity, because these cards use
41 a hardwired NuBus interrupt and a magic ISAIRQ value in the card.
43 * Basically eliminated everything not relevant to getting the
44 cards minimally functioning on the Macintosh.
46 I might add that these cards are badly designed even from the Mac
47 standpoint, in that Dayna, in their infinite wisdom, used NuBus slot
48 I/O space and NuBus interrupts for these cards, but neglected to
49 provide anything even remotely resembling a NuBus ROM. Therefore we
50 have to probe for them in a brain-damaged ISA-like fashion.
52 Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 11/01/2001
53 check kmalloc and release the allocated memory on failure in
54 mac89x0_probe and in init_module
55 use local_irq_{save,restore}(flags) in net_get_stat, not just
56 local_irq_{dis,en}able()
59 static char *version =
60 "cs89x0.c:v1.02 11/26/96 Russell Nelson <nelson@crynwr.com>\n";
62 /* ======================= configure the driver here ======================= */
64 /* use 0 for production, 1 for verification, >2 for debug */
65 #ifndef NET_DEBUG
66 #define NET_DEBUG 0
67 #endif
69 /* ======================= end of configuration ======================= */
72 /* Always include 'config.h' first in case the user wants to turn on
73 or override something. */
74 #include <linux/module.h>
76 #define PRINTK(x) printk x
79 Sources:
81 Crynwr packet driver epktisa.
83 Crystal Semiconductor data sheets.
87 #include <linux/kernel.h>
88 #include <linux/types.h>
89 #include <linux/fcntl.h>
90 #include <linux/interrupt.h>
91 #include <linux/ioport.h>
92 #include <linux/in.h>
93 #include <linux/slab.h>
94 #include <linux/string.h>
95 #include <linux/nubus.h>
96 #include <linux/errno.h>
97 #include <linux/init.h>
98 #include <linux/netdevice.h>
99 #include <linux/etherdevice.h>
100 #include <linux/skbuff.h>
102 #include <asm/system.h>
103 #include <asm/bitops.h>
104 #include <asm/io.h>
105 #include <asm/hwtest.h>
106 #include <asm/macints.h>
108 #include "cs89x0.h"
110 static unsigned int net_debug = NET_DEBUG;
112 /* Information that need to be kept for each board. */
113 struct net_local {
114 struct net_device_stats stats;
115 int chip_type; /* one of: CS8900, CS8920, CS8920M */
116 char chip_revision; /* revision letter of the chip ('A'...) */
117 int send_cmd; /* the propercommand used to send a packet. */
118 int rx_mode;
119 int curr_rx_cfg;
120 int send_underrun; /* keep track of how many underruns in a row we get */
121 struct sk_buff *skb;
124 /* Index to functions, as function prototypes. */
126 extern int mac89x0_probe(struct net_device *dev);
127 #if 0
128 extern void reset_chip(struct net_device *dev);
129 #endif
130 static int net_open(struct net_device *dev);
131 static int net_send_packet(struct sk_buff *skb, struct net_device *dev);
132 static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs *regs);
133 static void set_multicast_list(struct net_device *dev);
134 static void net_rx(struct net_device *dev);
135 static int net_close(struct net_device *dev);
136 static struct net_device_stats *net_get_stats(struct net_device *dev);
137 static int set_mac_address(struct net_device *dev, void *addr);
140 /* Example routines you must write ;->. */
141 #define tx_done(dev) 1
143 /* For reading/writing registers ISA-style */
144 static inline int
145 readreg_io(struct net_device *dev, int portno)
147 nubus_writew(swab16(portno), dev->base_addr + ADD_PORT);
148 return swab16(nubus_readw(dev->base_addr + DATA_PORT));
151 static inline void
152 writereg_io(struct net_device *dev, int portno, int value)
154 nubus_writew(swab16(portno), dev->base_addr + ADD_PORT);
155 nubus_writew(swab16(value), dev->base_addr + DATA_PORT);
158 /* These are for reading/writing registers in shared memory */
159 static inline int
160 readreg(struct net_device *dev, int portno)
162 return swab16(nubus_readw(dev->mem_start + portno));
165 static inline void
166 writereg(struct net_device *dev, int portno, int value)
168 nubus_writew(swab16(value), dev->mem_start + portno);
171 /* Probe for the CS8900 card in slot E. We won't bother looking
172 anywhere else until we have a really good reason to do so. */
173 int __init mac89x0_probe(struct net_device *dev)
175 static int once_is_enough;
176 struct net_local *lp;
177 static unsigned version_printed;
178 int i, slot;
179 unsigned rev_type = 0;
180 unsigned long ioaddr;
181 unsigned short sig;
183 SET_MODULE_OWNER(dev);
185 if (once_is_enough)
186 return -ENODEV;
187 once_is_enough = 1;
189 /* We might have to parameterize this later */
190 slot = 0xE;
191 /* Get out now if there's a real NuBus card in slot E */
192 if (nubus_find_slot(slot, NULL) != NULL)
193 return -ENODEV;
195 /* The pseudo-ISA bits always live at offset 0x300 (gee,
196 wonder why...) */
197 ioaddr = (unsigned long)
198 nubus_slot_addr(slot) | (((slot&0xf) << 20) + DEFAULTIOBASE);
200 unsigned long flags;
201 int card_present;
203 local_irq_save(flags);
204 card_present = hwreg_present((void*) ioaddr+4)
205 && hwreg_present((void*) ioaddr + DATA_PORT);
206 local_irq_restore(flags);
208 if (!card_present)
209 return -ENODEV;
212 nubus_writew(0, ioaddr + ADD_PORT);
213 sig = nubus_readw(ioaddr + DATA_PORT);
214 if (sig != swab16(CHIP_EISA_ID_SIG))
215 return -ENODEV;
217 /* Initialize the net_device structure. */
218 if (dev->priv == NULL) {
219 dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
220 if (!dev->priv)
221 return -ENOMEM;
222 memset(dev->priv, 0, sizeof(struct net_local));
224 lp = (struct net_local *)dev->priv;
226 /* Fill in the 'dev' fields. */
227 dev->base_addr = ioaddr;
228 dev->mem_start = (unsigned long)
229 nubus_slot_addr(slot) | (((slot&0xf) << 20) + MMIOBASE);
230 dev->mem_end = dev->mem_start + 0x1000;
232 /* Turn on shared memory */
233 writereg_io(dev, PP_BusCTL, MEMORY_ON);
235 /* get the chip type */
236 rev_type = readreg(dev, PRODUCT_ID_ADD);
237 lp->chip_type = rev_type &~ REVISON_BITS;
238 lp->chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
240 /* Check the chip type and revision in order to set the correct send command
241 CS8920 revision C and CS8900 revision F can use the faster send. */
242 lp->send_cmd = TX_AFTER_381;
243 if (lp->chip_type == CS8900 && lp->chip_revision >= 'F')
244 lp->send_cmd = TX_NOW;
245 if (lp->chip_type != CS8900 && lp->chip_revision >= 'C')
246 lp->send_cmd = TX_NOW;
248 if (net_debug && version_printed++ == 0)
249 printk(version);
251 printk(KERN_INFO "%s: cs89%c0%s rev %c found at %#8lx",
252 dev->name,
253 lp->chip_type==CS8900?'0':'2',
254 lp->chip_type==CS8920M?"M":"",
255 lp->chip_revision,
256 dev->base_addr);
258 /* Try to read the MAC address */
259 if ((readreg(dev, PP_SelfST) & (EEPROM_PRESENT | EEPROM_OK)) == 0) {
260 printk("\nmac89x0: No EEPROM, giving up now.\n");
261 kfree(dev->priv);
262 dev->priv = NULL;
263 return -ENODEV;
264 } else {
265 for (i = 0; i < ETH_ALEN; i += 2) {
266 /* Big-endian (why??!) */
267 unsigned short s = readreg(dev, PP_IA + i);
268 dev->dev_addr[i] = s >> 8;
269 dev->dev_addr[i+1] = s & 0xff;
273 dev->irq = SLOT2IRQ(slot);
274 printk(" IRQ %d ADDR ", dev->irq);
276 /* print the ethernet address. */
277 for (i = 0; i < ETH_ALEN; i++)
278 printk("%2.2x%s", dev->dev_addr[i],
279 ((i < ETH_ALEN-1) ? ":" : ""));
281 dev->open = net_open;
282 dev->stop = net_close;
283 dev->hard_start_xmit = net_send_packet;
284 dev->get_stats = net_get_stats;
285 dev->set_multicast_list = &set_multicast_list;
286 dev->set_mac_address = &set_mac_address;
288 /* Fill in the fields of the net_device structure with ethernet values. */
289 ether_setup(dev);
291 printk("\n");
292 return 0;
295 #if 0
296 /* This is useful for something, but I don't know what yet. */
297 void __init reset_chip(struct net_device *dev)
299 int reset_start_time;
301 writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
303 /* wait 30 ms */
304 current->state = TASK_INTERRUPTIBLE;
305 schedule_timeout(30*HZ/1000);
307 /* Wait until the chip is reset */
308 reset_start_time = jiffies;
309 while( (readreg(dev, PP_SelfST) & INIT_DONE) == 0 && jiffies - reset_start_time < 2)
312 #endif
314 /* Open/initialize the board. This is called (in the current kernel)
315 sometime after booting when the 'ifconfig' program is run.
317 This routine should set everything up anew at each open, even
318 registers that "should" only need to be set once at boot, so that
319 there is non-reboot way to recover if something goes wrong.
321 static int
322 net_open(struct net_device *dev)
324 struct net_local *lp = (struct net_local *)dev->priv;
325 int i;
327 /* Disable the interrupt for now */
328 writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) & ~ENABLE_IRQ);
330 /* Grab the interrupt */
331 if (request_irq(dev->irq, &net_interrupt, 0, "cs89x0", dev))
332 return -EAGAIN;
334 /* Set up the IRQ - Apparently magic */
335 if (lp->chip_type == CS8900)
336 writereg(dev, PP_CS8900_ISAINT, 0);
337 else
338 writereg(dev, PP_CS8920_ISAINT, 0);
340 /* set the Ethernet address */
341 for (i=0; i < ETH_ALEN/2; i++)
342 writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
344 /* Turn on both receive and transmit operations */
345 writereg(dev, PP_LineCTL, readreg(dev, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
347 /* Receive only error free packets addressed to this card */
348 lp->rx_mode = 0;
349 writereg(dev, PP_RxCTL, DEF_RX_ACCEPT);
351 lp->curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL;
353 writereg(dev, PP_RxCFG, lp->curr_rx_cfg);
355 writereg(dev, PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL |
356 TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
358 writereg(dev, PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL |
359 TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL);
361 /* now that we've got our act together, enable everything */
362 writereg(dev, PP_BusCTL, readreg(dev, PP_BusCTL) | ENABLE_IRQ);
363 netif_start_queue(dev);
364 return 0;
367 static int
368 net_send_packet(struct sk_buff *skb, struct net_device *dev)
370 if (dev->tbusy) {
371 /* If we get here, some higher level has decided we are broken.
372 There should really be a "kick me" function call instead. */
373 int tickssofar = jiffies - dev->trans_start;
374 if (tickssofar < 5)
375 return 1;
376 if (net_debug > 0) printk("%s: transmit timed out, %s?\n", dev->name,
377 tx_done(dev) ? "IRQ conflict" : "network cable problem");
378 /* Try to restart the adaptor. */
379 dev->tbusy=0;
380 dev->trans_start = jiffies;
383 /* Block a timer-based transmit from overlapping. This could better be
384 done with atomic_swap(1, dev->tbusy), but set_bit() works as well. */
385 if (test_and_set_bit(0, (void*)&dev->tbusy) != 0)
386 printk("%s: Transmitter access conflict.\n", dev->name);
387 else {
388 struct net_local *lp = (struct net_local *)dev->priv;
389 unsigned long flags;
391 if (net_debug > 3)
392 printk("%s: sent %d byte packet of type %x\n",
393 dev->name, skb->len,
394 (skb->data[ETH_ALEN+ETH_ALEN] << 8)
395 | skb->data[ETH_ALEN+ETH_ALEN+1]);
397 /* keep the upload from being interrupted, since we
398 ask the chip to start transmitting before the
399 whole packet has been completely uploaded. */
400 local_irq_save(flags);
402 /* initiate a transmit sequence */
403 writereg(dev, PP_TxCMD, lp->send_cmd);
404 writereg(dev, PP_TxLength, skb->len);
406 /* Test to see if the chip has allocated memory for the packet */
407 if ((readreg(dev, PP_BusST) & READY_FOR_TX_NOW) == 0) {
408 /* Gasp! It hasn't. But that shouldn't happen since
409 we're waiting for TxOk, so return 1 and requeue this packet. */
410 local_irq_restore(flags);
411 return 1;
414 /* Write the contents of the packet */
415 memcpy_toio(dev->mem_start + PP_TxFrame, skb->data, skb->len+1);
417 local_irq_restore(flags);
418 dev->trans_start = jiffies;
420 dev_kfree_skb (skb);
422 return 0;
425 /* The typical workload of the driver:
426 Handle the network interface interrupts. */
427 static irqreturn_t net_interrupt(int irq, void *dev_id, struct pt_regs * regs)
429 struct net_device *dev = dev_id;
430 struct net_local *lp;
431 int ioaddr, status;
433 if (dev == NULL) {
434 printk ("net_interrupt(): irq %d for unknown device.\n", irq);
435 return IRQ_NONE;
437 if (dev->interrupt)
438 printk("%s: Re-entering the interrupt handler.\n", dev->name);
439 dev->interrupt = 1;
441 ioaddr = dev->base_addr;
442 lp = (struct net_local *)dev->priv;
444 /* we MUST read all the events out of the ISQ, otherwise we'll never
445 get interrupted again. As a consequence, we can't have any limit
446 on the number of times we loop in the interrupt handler. The
447 hardware guarantees that eventually we'll run out of events. Of
448 course, if you're on a slow machine, and packets are arriving
449 faster than you can read them off, you're screwed. Hasta la
450 vista, baby! */
451 while ((status = swab16(nubus_readw(dev->base_addr + ISQ_PORT)))) {
452 if (net_debug > 4)printk("%s: event=%04x\n", dev->name, status);
453 switch(status & ISQ_EVENT_MASK) {
454 case ISQ_RECEIVER_EVENT:
455 /* Got a packet(s). */
456 net_rx(dev);
457 break;
458 case ISQ_TRANSMITTER_EVENT:
459 lp->stats.tx_packets++;
460 dev->tbusy = 0;
461 mark_bh(NET_BH); /* Inform upper layers. */
462 if ((status & TX_OK) == 0) lp->stats.tx_errors++;
463 if (status & TX_LOST_CRS) lp->stats.tx_carrier_errors++;
464 if (status & TX_SQE_ERROR) lp->stats.tx_heartbeat_errors++;
465 if (status & TX_LATE_COL) lp->stats.tx_window_errors++;
466 if (status & TX_16_COL) lp->stats.tx_aborted_errors++;
467 break;
468 case ISQ_BUFFER_EVENT:
469 if (status & READY_FOR_TX) {
470 /* we tried to transmit a packet earlier,
471 but inexplicably ran out of buffers.
472 That shouldn't happen since we only ever
473 load one packet. Shrug. Do the right
474 thing anyway. */
475 dev->tbusy = 0;
476 mark_bh(NET_BH); /* Inform upper layers. */
478 if (status & TX_UNDERRUN) {
479 if (net_debug > 0) printk("%s: transmit underrun\n", dev->name);
480 lp->send_underrun++;
481 if (lp->send_underrun == 3) lp->send_cmd = TX_AFTER_381;
482 else if (lp->send_underrun == 6) lp->send_cmd = TX_AFTER_ALL;
484 break;
485 case ISQ_RX_MISS_EVENT:
486 lp->stats.rx_missed_errors += (status >>6);
487 break;
488 case ISQ_TX_COL_EVENT:
489 lp->stats.collisions += (status >>6);
490 break;
493 dev->interrupt = 0;
494 return IRQ_HANDLED;
497 /* We have a good packet(s), get it/them out of the buffers. */
498 static void
499 net_rx(struct net_device *dev)
501 struct net_local *lp = (struct net_local *)dev->priv;
502 struct sk_buff *skb;
503 int status, length;
505 status = readreg(dev, PP_RxStatus);
506 if ((status & RX_OK) == 0) {
507 lp->stats.rx_errors++;
508 if (status & RX_RUNT) lp->stats.rx_length_errors++;
509 if (status & RX_EXTRA_DATA) lp->stats.rx_length_errors++;
510 if (status & RX_CRC_ERROR) if (!(status & (RX_EXTRA_DATA|RX_RUNT)))
511 /* per str 172 */
512 lp->stats.rx_crc_errors++;
513 if (status & RX_DRIBBLE) lp->stats.rx_frame_errors++;
514 return;
517 length = readreg(dev, PP_RxLength);
518 /* Malloc up new buffer. */
519 skb = alloc_skb(length, GFP_ATOMIC);
520 if (skb == NULL) {
521 printk("%s: Memory squeeze, dropping packet.\n", dev->name);
522 lp->stats.rx_dropped++;
523 return;
525 skb_put(skb, length);
526 skb->dev = dev;
528 memcpy_fromio(skb->data, dev->mem_start + PP_RxFrame, length);
530 if (net_debug > 3)printk("%s: received %d byte packet of type %x\n",
531 dev->name, length,
532 (skb->data[ETH_ALEN+ETH_ALEN] << 8)
533 | skb->data[ETH_ALEN+ETH_ALEN+1]);
535 skb->protocol=eth_type_trans(skb,dev);
536 netif_rx(skb);
537 dev->last_rx = jiffies;
538 lp->stats.rx_packets++;
539 lp->stats.rx_bytes += length;
542 /* The inverse routine to net_open(). */
543 static int
544 net_close(struct net_device *dev)
547 writereg(dev, PP_RxCFG, 0);
548 writereg(dev, PP_TxCFG, 0);
549 writereg(dev, PP_BufCFG, 0);
550 writereg(dev, PP_BusCTL, 0);
552 netif_stop_queue(dev);
554 free_irq(dev->irq, dev);
556 /* Update the statistics here. */
558 return 0;
562 /* Get the current statistics. This may be called with the card open or
563 closed. */
564 static struct net_device_stats *
565 net_get_stats(struct net_device *dev)
567 struct net_local *lp = (struct net_local *)dev->priv;
568 unsigned long flags;
570 local_irq_save(flags);
571 /* Update the statistics from the device registers. */
572 lp->stats.rx_missed_errors += (readreg(dev, PP_RxMiss) >> 6);
573 lp->stats.collisions += (readreg(dev, PP_TxCol) >> 6);
574 local_irq_restore(flags);
576 return &lp->stats;
579 static void set_multicast_list(struct net_device *dev)
581 struct net_local *lp = (struct net_local *)dev->priv;
583 if(dev->flags&IFF_PROMISC)
585 lp->rx_mode = RX_ALL_ACCEPT;
587 else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)
589 /* The multicast-accept list is initialized to accept-all, and we
590 rely on higher-level filtering for now. */
591 lp->rx_mode = RX_MULTCAST_ACCEPT;
593 else
594 lp->rx_mode = 0;
596 writereg(dev, PP_RxCTL, DEF_RX_ACCEPT | lp->rx_mode);
598 /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */
599 writereg(dev, PP_RxCFG, lp->curr_rx_cfg |
600 (lp->rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));
604 static int set_mac_address(struct net_device *dev, void *addr)
606 int i;
607 if (dev->start)
608 return -EBUSY;
609 printk("%s: Setting MAC address to ", dev->name);
610 for (i = 0; i < 6; i++)
611 printk(" %2.2x", dev->dev_addr[i] = ((unsigned char *)addr)[i]);
612 printk(".\n");
613 /* set the Ethernet address */
614 for (i=0; i < ETH_ALEN/2; i++)
615 writereg(dev, PP_IA+i*2, dev->dev_addr[i*2] | (dev->dev_addr[i*2+1] << 8));
617 return 0;
620 #ifdef MODULE
622 static struct net_device dev_cs89x0;
623 static int debug;
625 MODULE_PARM(debug, "i");
626 MODULE_PARM_DESC(debug, "CS89[02]0 debug level (0-5)");
627 MODULE_LICENSE("GPL");
630 init_module(void)
632 net_debug = debug;
633 dev_cs89x0.init = mac89x0_probe;
634 dev_cs89x0.priv = kmalloc(sizeof(struct net_local), GFP_KERNEL);
635 if (!dev_cs89x0.priv)
636 return -ENOMEM;
637 memset(dev_cs89x0.priv, 0, sizeof(struct net_local));
639 if (register_netdev(&dev_cs89x0) != 0) {
640 printk(KERN_WARNING "mac89x0.c: No card found\n");
641 kfree(dev_cs89x0.priv);
642 return -ENXIO;
644 return 0;
647 void
648 cleanup_module(void)
651 #endif
652 #ifdef MODULE
653 nubus_writew(0, dev_cs89x0.base_addr + ADD_PORT);
654 #endif
655 #ifdef MODULE
657 if (dev_cs89x0.priv != NULL) {
658 /* Free up the private structure, or leak memory :-) */
659 unregister_netdev(&dev_cs89x0);
660 kfree(dev_cs89x0.priv);
661 dev_cs89x0.priv = NULL; /* gets re-allocated by cs89x0_probe1 */
664 #endif /* MODULE */
667 * Local variables:
668 * compile-command: "m68k-linux-gcc -D__KERNEL__ -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -DMODULE -DMODVERSIONS -include ../../include/linux/modversions.h -c -o mac89x0.o mac89x0.c"
669 * version-control: t
670 * kept-new-versions: 5
671 * c-indent-level: 8
672 * tab-width: 8
673 * End: