* add p cc
[mascara-docs.git] / i386 / linux / linux-2.3.21 / drivers / net / macsonic.c
blobd14ccf3fb919a656bb245f936fca898505fa4746
1 /*
2 * macsonic.c
4 * (C) 1998 Alan Cox
6 * Debugging Andreas Ehliar, Michael Schmitz
8 * Based on code
9 * (C) 1996 by Thomas Bogendoerfer (tsbogend@bigbug.franken.de)
11 * This driver is based on work from Andreas Busse, but most of
12 * the code is rewritten.
14 * (C) 1995 by Andreas Busse (andy@waldorf-gmbh.de)
16 * A driver for the Mac onboard Sonic ethernet chip.
18 * 98/12/21 MSch: judged from tests on Q800, it's basically working,
19 * but eating up both receive and transmit resources
20 * and duplicating packets. Needs more testing.
22 * 99/01/03 MSch: upgraded to version 0.92 of the core driver, fixed.
25 #include <linux/kernel.h>
26 #include <linux/sched.h>
27 #include <linux/types.h>
28 #include <linux/ctype.h>
29 #include <linux/fcntl.h>
30 #include <linux/interrupt.h>
31 #include <linux/ptrace.h>
32 #include <linux/init.h>
33 #include <linux/ioport.h>
34 #include <linux/in.h>
35 #include <linux/malloc.h>
36 #include <linux/string.h>
37 #include <linux/delay.h>
38 #include <linux/nubus.h>
39 #include <asm/bootinfo.h>
40 #include <asm/system.h>
41 #include <asm/bitops.h>
42 #include <asm/pgtable.h>
43 #include <asm/segment.h>
44 #include <asm/io.h>
45 #include <asm/dma.h>
46 #include <asm/macintosh.h>
48 #include <linux/errno.h>
50 #include <linux/netdevice.h>
51 #include <linux/etherdevice.h>
52 #include <linux/skbuff.h>
54 #include <config/macsonic.h>
56 #define SREGS_PAD(n) u16 n;
58 #include "sonic.h"
60 extern int mac_onboard_sonic_probe(void);
62 static int setup_debug = -1;
63 static int setup_offset = -1;
64 static int setup_shift = -1;
67 * This seems to be the right default for the Q800
70 static int reg_offset = 0;
71 static int reg_shift = 0;
74 * Macros to access SONIC registers
77 #define MAC_SONIC_REGISTERS 0x50F0A000
78 #define MAC_SONIC_PROM_BASE 0x50f08000
79 #define MAC_SONIC_IRQ 9 /* Nubus 9 */
82 * FIXME: We may need to invert the byte ordering. These should
83 * be ok for other aspects as they are uncached spaces.
84 * The original macros from jazzsonic.c works for me
85 * on my LC 630, YMMV /Andreas Ehliar
88 #if 0
89 #define SONIC_READ(reg) \
90 *((volatile unsigned int *)base_addr+((reg)<<2)+2)
92 #define SONIC_WRITE(reg,val) \
93 *((volatile unsigned int *)base_addr+((reg)<<2)+2) = val
94 #else
95 #define SONIC_READ(reg) \
96 *((volatile unsigned int *)base_addr+reg)
98 #define SONIC_WRITE(reg,val) \
99 *((volatile unsigned int *)base_addr+reg) = val
100 #endif
102 #define SONIC_READ_PROM(addr) \
103 *((volatile unsigned char *)prom_addr+addr)
105 * Function : mac_sonic_setup(char *str, int *ints)
107 * Purpose : booter command line initialization of the overrides array,
109 * Inputs : str - unused, ints - array of integer parameters with ints[0]
110 * equal to the number of ints.
112 * Currently unused in the new driver; need to add settable parameters to the
113 * detect function.
117 void mac_sonic_setup(char *str, int *ints) {
118 /* Format of macsonic parameter is:
119 * macsonic=<debug>,<offset>,<shift>
120 * Negative values mean don't change.
123 /* Grmbl... the standard parameter parsing can't handle negative numbers
124 * :-( So let's do it ourselves!
127 int i = ints[0]+1, fact;
129 while( str && (isdigit(*str) || *str == '-') && i <= 10) {
130 if (*str == '-')
131 fact = -1, ++str;
132 else
133 fact = 1;
134 ints[i++] = simple_strtoul( str, NULL, 0 ) * fact;
135 if ((str = strchr( str, ',' )) != NULL)
136 ++str;
138 ints[0] = i-1;
140 if (ints[0] < 1) {
141 printk( "mac_sonic_setup: no arguments!\n" );
142 return;
145 if (ints[0] >= 1) {
146 /* 0 <= n <= 2 */
147 if (ints[1] >= 0 && ints[1] <= 8)
148 setup_debug = ints[1];
149 else if (ints[1] > 16)
150 printk( "mac_sonic_setup: invalid debug level %d !\n", ints[1] );
152 if (ints[0] >= 2) {
153 /* 0 <= n <= 2 */
154 if (ints[2] >= 0 && ints[2] <= 16)
155 setup_offset = ints[2];
156 else if (ints[2] > 16)
157 printk( "mac_sonic_setup: invalid offset %d !\n", ints[2] );
159 if (ints[0] >= 3) {
160 /* 0 <= n <= 2 */
161 if (ints[3] >= 0 && ints[3] <= 16)
162 setup_shift = ints[3];
163 else if (ints[3] > 16)
164 printk( "mac_sonic_setup: invalid shift %d !\n", ints[3] );
168 static int sonic_debug = 0;
171 * For reversing the PROM address
174 static unsigned char nibbletab[] = {0, 8, 4, 12, 2, 10, 6, 14,
175 1, 9, 5, 13, 3, 11, 7, 15};
177 int __init mac_onboard_sonic_probe(void)
179 struct net_device *dev;
180 unsigned int silicon_revision;
181 unsigned int val;
182 struct sonic_local *lp;
183 int i;
184 int base_addr = MAC_SONIC_REGISTERS;
185 int prom_addr = MAC_SONIC_PROM_BASE;
186 static int one=0;
188 if (!MACH_IS_MAC)
189 return -ENODEV;
191 if(++one!=1) /* Only one is allowed */
192 return -ENODEV;
194 printk(KERN_INFO "Checking for internal Macintosh ethernet (SONIC).. ");
196 if (macintosh_config->ether_type != MAC_ETHER_SONIC)
198 printk("none.\n");
199 return -ENODEV;
202 printk("yes\n");
204 if (setup_debug >= 0)
205 sonic_debug = setup_debug;
208 * This may depend on the actual Mac model ... works for me.
210 reg_offset =
211 (setup_offset >= 0) ? setup_offset : 0;
212 reg_shift =
213 (setup_shift >= 0) ? setup_shift : 0;
216 * get the Silicon Revision ID. If this is one of the known
217 * one assume that we found a SONIC ethernet controller at
218 * the expected location.
219 * (This is not implemented in the Macintosh driver yet; need
220 * to collect values from various sources. Mine is 0x4 ...)
223 silicon_revision = SONIC_READ(SONIC_SR);
224 if (sonic_debug > 1)
225 printk("SONIC Silicon Revision = 0x%04x\n", silicon_revision);
228 * We need to allocate sonic_local later on, making sure it's
229 * aligned on a 64k boundary. So, no space for dev->priv allocated
230 * here ...
232 dev = init_etherdev(0,0);
234 if(dev==NULL)
235 return -ENOMEM;
237 printk("%s: %s found at 0x%08x, ",
238 dev->name, "SONIC ethernet", base_addr);
240 if (sonic_debug > 1)
241 printk("using offset %d shift %d,", reg_offset, reg_shift);
243 /* Fill in the 'dev' fields. */
244 dev->base_addr = base_addr;
245 dev->irq = MAC_SONIC_IRQ;
248 * Put the sonic into software reset, then
249 * retrieve and print the ethernet address.
252 SONIC_WRITE(SONIC_CMD, SONIC_CR_RST);
255 * We can't trust MacOS to initialise things it seems.
258 if (sonic_debug > 1)
259 printk("SONIC_DCR was %X\n",SONIC_READ(SONIC_DCR));
261 SONIC_WRITE(SONIC_DCR,
262 SONIC_DCR_RFT1 | SONIC_DCR_TFT0 | SONIC_DCR_EXBUS | SONIC_DCR_DW);
265 * We don't want floating spare IRQ's around, not on
266 * level triggered systems!
267 * Strange though - writing to the ISR only clears currently
268 * pending IRQs, but doesn't disable them... Does this make
269 * a difference?? Seems it does ...
271 #if 1
272 SONIC_WRITE(SONIC_ISR,0x7fff);
273 SONIC_WRITE(SONIC_IMR,0);
274 #else
275 SONIC_WRITE(SONIC_ISR, SONIC_IMR_DEFAULT);
276 #endif
278 /* This is how it is done in jazzsonic.c
279 * It doesn't seem to work here though.
281 if (sonic_debug > 2) {
282 printk("Retreiving CAM entry 0. This should be the HW address.\n");
284 SONIC_WRITE(SONIC_CEP, 0);
285 for (i = 0; i < 3; i++)
287 val = SONIC_READ(SONIC_CAP0 - i);
288 dev->dev_addr[i * 2] = val;
289 dev->dev_addr[i * 2 + 1] = val >> 8;
292 printk("HW Address from CAM 0: ");
293 for (i = 0; i < 6; i++)
295 printk("%2.2x", dev->dev_addr[i]);
296 if (i < 5)
297 printk(":");
299 printk("\n");
301 printk("Retreiving CAM entry 15. Another candidate...\n");
304 * MacOS seems to use CAM entry 15 ...
306 SONIC_WRITE(SONIC_CEP, 15);
307 for (i = 0; i < 3; i++)
309 val = SONIC_READ(SONIC_CAP0 - i);
310 dev->dev_addr[i * 2] = val;
311 dev->dev_addr[i * 2 + 1] = val >> 8;
314 printk("HW Address from CAM 15: ");
315 for (i = 0; i < 6; i++)
317 printk("%2.2x", dev->dev_addr[i]);
318 if (i < 5)
319 printk(":");
321 printk("\n");
325 * if we can read the PROM, we're safe :-)
327 if (sonic_debug > 1)
328 printk("Retreiving HW address from the PROM: ");
330 for(i=0;i<6;i++){
331 dev->dev_addr[i]=SONIC_READ_PROM(i);
333 if (sonic_debug > 1) {
334 for (i = 0; i < 6; i++)
336 printk("%2.2x", dev->dev_addr[i]);
337 if (i < 5)
338 printk(":");
340 printk("\n");
343 * If its not one of these we have
344 * screwed up on this Mac model
347 if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
348 memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
349 memcmp(dev->dev_addr, "\x00\x05\x02", 3))
352 * Try bit reversed
354 for(i=0;i<6;i++){
355 val = SONIC_READ_PROM(i);
356 dev->dev_addr[i]=(nibbletab[val & 0xf] << 4) |
357 nibbletab[(val >> 4) &0xf];
359 if (sonic_debug > 1) {
360 printk("Trying bit reversed: ");
361 for (i = 0; i < 6; i++)
363 printk("%2.2x", dev->dev_addr[i]);
364 if (i < 5)
365 printk(":");
367 printk("\n");
369 if (memcmp(dev->dev_addr, "\x08\x00\x07", 3) &&
370 memcmp(dev->dev_addr, "\x00\xA0\x40", 3) &&
371 memcmp(dev->dev_addr, "\x00\x05\x02", 3))
374 * Still nonsense ... messed up someplace!
376 printk("ERROR (INVALID MAC)\n");
377 return -EIO;
381 printk(" MAC ");
382 for (i = 0; i < 6; i++)
384 printk("%2.2x", dev->dev_addr[i]);
385 if (i < 5)
386 printk(":");
389 printk(" IRQ %d\n", MAC_SONIC_IRQ);
391 /* Initialize the device structure. */
392 if (dev->priv == NULL)
394 if (sonic_debug > 2) {
395 printk("Allocating memory for dev->priv aka lp\n");
396 printk("Memory to allocate: %d\n",sizeof(*lp));
399 * the memory be located in the same 64kb segment
401 lp = NULL;
402 i = 0;
405 lp = (struct sonic_local *) kmalloc(sizeof(*lp), GFP_KERNEL);
406 if ((unsigned long) lp >> 16 != ((unsigned long) lp + sizeof(*lp)) >> 16)
408 /* FIXME, free the memory later */
409 kfree(lp);
410 lp = NULL;
413 while (lp == NULL && i++ < 20);
415 if (lp == NULL)
417 printk("%s: couldn't allocate memory for descriptors\n",
418 dev->name);
419 return -ENOMEM;
422 if (sonic_debug > 2) {
423 printk("Memory allocated after %d tries\n",i);
426 /* XXX sonic_local has the TDA, RRA, RDA, don't cache */
427 kernel_set_cachemode((u32)lp, 8192, IOMAP_NOCACHE_SER);
428 memset(lp, 0, sizeof(struct sonic_local));
430 lp->cda_laddr = (u32)lp;
431 if (sonic_debug > 2) {
432 printk("memory allocated for sonic at 0x%x\n",lp);
434 lp->tda_laddr = lp->cda_laddr + sizeof(lp->cda);
435 lp->rra_laddr = lp->tda_laddr + sizeof(lp->tda);
436 lp->rda_laddr = lp->rra_laddr + sizeof(lp->rra);
438 /* allocate receive buffer area */
439 /* FIXME, maybe we should use skbs */
440 if ((lp->rba = (char *) kmalloc(SONIC_NUM_RRS * SONIC_RBSIZE, GFP_KERNEL)) == NULL)
442 printk("%s: couldn't allocate receive buffers\n", dev->name);
443 return -ENOMEM;
445 /* XXX RBA written by Sonic, not cached either */
446 kernel_set_cachemode((u32)lp->rba, 6*8192, IOMAP_NOCACHE_SER);
447 lp->rba_laddr = (u32)lp->rba;
448 flush_cache_all();
449 dev->priv = (struct sonic_local *) lp;
451 lp = (struct sonic_local *) dev->priv;
452 dev->open = sonic_open;
453 dev->stop = sonic_close;
454 dev->hard_start_xmit = sonic_send_packet;
455 dev->get_stats = sonic_get_stats;
456 dev->set_multicast_list = &sonic_multicast_list;
458 /* Fill in the fields of the device structure with ethernet values. */
459 ether_setup(dev);
460 return 0;
464 * SONIC uses a nubus IRQ
467 #define sonic_request_irq(irq, vec, flags, name, dev) \
468 nubus_request_irq(irq, dev, vec)
469 #define sonic_free_irq(irq,id) nubus_free_irq(irq)
472 * No funnies on memory mapping.
475 #define sonic_chiptomem(x) (x)
478 * No VDMA on a Macintosh. So we need request no such facility.
481 #define vdma_alloc(x,y) ((u32)(x))
482 #define vdma_free(x)
483 #define PHYSADDR(x) (x)
485 #include "sonic.c"