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

Linux Cross Reference
Linux/drivers/net/daynaport.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* daynaport.c: A Macintosh 8390 based ethernet driver for linux. */
  2 /*
  3         Derived from code:
  4         
  5         Written 1993-94 by Donald Becker.
  6 
  7         Copyright 1993 United States Government as represented by the
  8         Director, National Security Agency.
  9 
 10         This software may be used and distributed according to the terms
 11         of the GNU Public License, incorporated herein by reference.
 12 
 13             TODO:
 14 
 15             The block output routines may be wrong for non Dayna
 16             cards
 17 
 18                 Fix this driver so that it will attempt to use the info
 19                 (i.e. iobase, iosize) given to it by the new and improved
 20                 NuBus code.
 21 
 22                 Despite its misleading filename, this driver is not Dayna-specific
 23                 anymore. */
 24 /* Cabletron E6100 card support added by Tony Mantler (eek@escape.ca) April 1999 */
 25 
 26 static const char *version =
 27         "daynaport.c: v0.02 1999-05-17 Alan Cox (Alan.Cox@linux.org) and others\n";
 28 static int version_printed;
 29 
 30 #include <linux/module.h>
 31 #include <linux/init.h>
 32 #include <linux/kernel.h>
 33 #include <linux/sched.h>
 34 #include <linux/errno.h>
 35 #include <linux/string.h>
 36 #include <linux/nubus.h>
 37 #include <asm/io.h>
 38 #include <asm/system.h>
 39 #include <asm/hwtest.h>
 40 #include <asm/macints.h>
 41 #include <linux/delay.h>
 42 
 43 #include <linux/netdevice.h>
 44 #include <linux/etherdevice.h>
 45 #include "8390.h"
 46 
 47 int ns8390_probe1(struct net_device *dev, int word16, char *name, int id,
 48                                   int prom, struct nubus_dev *ndev);
 49 
 50 static int ns8390_open(struct net_device *dev);
 51 static void ns8390_no_reset(struct net_device *dev);
 52 static int ns8390_close_card(struct net_device *dev);
 53 
 54 /* Interlan */
 55 static void interlan_reset(struct net_device *dev);
 56 
 57 /* Dayna */
 58 static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 59                                                 int ring_page);
 60 static void dayna_block_input(struct net_device *dev, int count,
 61                                                   struct sk_buff *skb, int ring_offset);
 62 static void dayna_block_output(struct net_device *dev, int count,
 63                                                    const unsigned char *buf, const int start_page);
 64 
 65 /* Sane (32-bit chunk memory read/write) */
 66 static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 67                                                 int ring_page);
 68 static void sane_block_input(struct net_device *dev, int count,
 69                                                   struct sk_buff *skb, int ring_offset);
 70 static void sane_block_output(struct net_device *dev, int count,
 71                                                    const unsigned char *buf, const int start_page);
 72 
 73 /* Slow Sane (16-bit chunk memory read/write) */
 74 static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
 75                                                 int ring_page);
 76 static void slow_sane_block_input(struct net_device *dev, int count,
 77                                                   struct sk_buff *skb, int ring_offset);
 78 static void slow_sane_block_output(struct net_device *dev, int count,
 79                                                    const unsigned char *buf, const int start_page);
 80 
 81 
 82 #define WD_START_PG     0x00    /* First page of TX buffer */
 83 #define WD03_STOP_PG    0x20    /* Last page +1 of RX ring */
 84 #define WD13_STOP_PG    0x40    /* Last page +1 of RX ring */
 85 
 86 #define CABLETRON_RX_START_PG          0x00    /* First page of RX buffer */
 87 #define CABLETRON_RX_STOP_PG           0x30    /* Last page +1 of RX ring */
 88 #define CABLETRON_TX_START_PG          CABLETRON_RX_STOP_PG  /* First page of TX buffer */
 89 
 90 
 91 #define DAYNA_MAC_BASE          0xf0007
 92 #define DAYNA_8390_BASE         0x80000 /* 3 */
 93 #define DAYNA_8390_MEM          0x00000
 94 #define DAYNA_MEMSIZE           0x04000 /* First word of each long ! */
 95 
 96 #define APPLE_8390_BASE         0xE0000
 97 #define APPLE_8390_MEM          0xD0000
 98 #define APPLE_MEMSIZE           8192    /* FIXME: need to dynamically check */
 99 
100 #define KINETICS_MAC_BASE       0xf0004 /* first byte of each long */
101 #define KINETICS_8390_BASE      0x80000
102 #define KINETICS_8390_MEM       0x00000 /* first word of each long */
103 #define KINETICS_MEMSIZE        8192    /* FIXME: need to dynamically check */
104 /*#define KINETICS_MEMSIZE      (0x10000/2) * CSA: on the board I have, at least */
105 
106 #define CABLETRON_8390_BASE             0x90000 
107 #define CABLETRON_8390_MEM              0x00000
108 
109 static int test_8390(volatile char *ptr, int scale)
110 {
111         int regd;
112         int v;
113         
114         if(hwreg_present(&ptr[0x00])==0)
115                 return -EIO;
116         if(hwreg_present(&ptr[0x0D<<scale])==0)
117                 return -EIO;
118         if(hwreg_present(&ptr[0x0D<<scale])==0)
119                 return -EIO;
120         ptr[0x00]=E8390_NODMA+E8390_PAGE1+E8390_STOP;
121         regd=ptr[0x0D<<scale];
122         ptr[0x0D<<scale]=0xFF;
123         ptr[0x00]=E8390_NODMA+E8390_PAGE0;
124         v=ptr[0x0D<<scale];
125         if(ptr[0x0D<<scale]!=0)
126         {
127                 ptr[0x0D<<scale]=regd;
128                 return -ENODEV;
129         }
130 /*      printk("NS8390 found at %p scaled %d\n", ptr,scale);*/
131         return 0;
132 }
133 /*
134  *    Identify the species of NS8390 card/driver we need
135  */
136 
137 enum mac8390_type {
138         NS8390_DAYNA,
139         NS8390_INTERLAN,
140         NS8390_KINETICS,
141         NS8390_APPLE,
142         NS8390_FARALLON,
143         NS8390_ASANTE,
144         NS8390_CABLETRON
145 };
146 
147 int __init ns8390_ident(struct nubus_dev* ndev)
148 {
149         /* This really needs to be tested and tested hard.  */
150                 
151         /* Summary of what we know so far --
152          * SW: 0x0104 -- asante,    16 bit, back4_offsets
153          * SW: 0x010b -- daynaport, 16 bit, fwrd4_offsets
154          * SW: 0x010c -- farallon,  16 bit, back4_offsets, no long word access
155          * SW: 0x011a -- focus,     [no details yet]
156          * SW: ?????? -- interlan,  16 bit, back4_offsets, funny reset
157          * SW: ?????? -- kinetics,   8 bit, back4_offsets
158          * -- so i've this hypothesis going that says DrSW&1 says whether the
159          *    map is forward or backwards -- and maybe DrSW&256 says what the
160          *    register spacing is -- for all cards that report a DrSW in some
161          *    range.
162          *    This would allow the "apple compatible" driver to drive many
163          *    seemingly different types of cards.  More DrSW info is needed
164          *    to investigate this properly. [CSA, 21-May-1999]
165          */
166         /* Dayna ex Kinetics board */
167         if(ndev->dr_sw == NUBUS_DRSW_DAYNA)
168                 return NS8390_DAYNA;
169         if(ndev->dr_sw == NUBUS_DRSW_ASANTE)
170                 return NS8390_ASANTE;
171         if(ndev->dr_sw == NUBUS_DRSW_FARALLON) /* farallon or sonic systems */
172                 return NS8390_FARALLON;
173         if(ndev->dr_sw == NUBUS_DRSW_KINETICS)
174                 return NS8390_KINETICS;
175         /* My ATI Engineering card with this combination crashes the */
176         /* driver trying to xmit packets. Best not touch it for now. */
177         /*     - 1999-05-20 (funaho@jurai.org)                       */
178         if(ndev->dr_sw == NUBUS_DRSW_FOCUS)
179                 return -1;
180 
181         /* Check the HW on this one, because it shares the same DrSW as
182            the on-board SONIC chips */
183         if(ndev->dr_hw == NUBUS_DRHW_CABLETRON)
184                 return NS8390_CABLETRON;
185         /* does anyone have one of these? */
186         if(ndev->dr_hw == NUBUS_DRHW_INTERLAN)
187                 return NS8390_INTERLAN;
188 
189         /* FIXME: what do genuine Apple boards look like? */
190         return -1;
191 }
192 
193 /*
194  *      Memory probe for 8390 cards
195  */
196  
197 int __init apple_8390_mem_probe(volatile unsigned short *p)
198 {
199         int i, j;
200         /*
201          *      Algorithm.
202          *      1.      Check each block size of memory doesn't fault
203          *      2.      Write a value to it
204          *      3.      Check all previous blocks are unaffected
205          */
206         
207         for(i=0;i<2;i++)
208         {
209                 volatile unsigned short *m=p+4096*i;
210                 /* Unwriteable - we have a fully decoded card and the
211                    RAM end located */
212                    
213                 if(hwreg_present(m)==0)
214                         return 8192*i;
215                         
216                 *m=0xA5A0|i;
217                 
218                 for(j=0;j<i;j++)
219                 {
220                         /* Partial decode and wrap ? */
221                         if(p[4096*j]!=(0xA5A0|j))
222                         {
223                                 /* This is the first misdecode, so it had
224                                    one less page than we tried */
225                                 return 8192*i;
226                         }
227                         j++;
228                 }
229                 /* Ok it still decodes.. move on 8K */
230         }
231         /* 
232          *      We don't look past 16K. That should cover most cards
233          *      and above 16K there isnt really any gain.
234          */
235         return 16384;
236  }
237                 
238 /*
239  *    Probe for 8390 cards.  
240  *    The ns8390_probe1() routine initializes the card and fills the
241  *    station address field.
242  *
243  *    The NuBus interface has changed!  We now scan for these somewhat
244  *    like how the PCI and Zorro drivers do.  It's not clear whether
245  *    this is actually better, but it makes things more consistent.
246  *
247  *    dev->mem_start points
248  *    at the memory ring, dev->mem_end gives the end of it.
249  */
250 
251 int __init mac8390_probe(struct net_device *dev)
252 {
253         static int slots = 0;
254         volatile unsigned short *i;
255         volatile unsigned char *p;
256         int plen;
257         int id;
258         static struct nubus_dev* ndev = NULL;
259 
260         /* Find the first card that hasn't already been seen */
261         while ((ndev = nubus_find_type(NUBUS_CAT_NETWORK,
262                                                                    NUBUS_TYPE_ETHERNET, ndev)) != NULL) {
263                 /* Have we seen it already? */
264                 if (slots & (1<<ndev->board->slot))
265                         continue;
266                 slots |= 1<<ndev->board->slot;
267 
268                 /* Is it one of ours? */
269                 if ((id = ns8390_ident(ndev)) != -1)
270                         break;
271         }
272 
273         /* Hm.  No more cards, then */
274         if (ndev == NULL)
275                 return -ENODEV;
276 
277         dev = init_etherdev(dev, 0);
278 
279         if (!version_printed) {
280                 printk(KERN_INFO "%s", version);
281                 version_printed = 1;
282         }
283 
284         /*
285          *      Dayna specific init
286          */
287         if(id==NS8390_DAYNA)
288         {
289                 dev->base_addr = (int)(ndev->board->slot_addr+DAYNA_8390_BASE);
290                 dev->mem_start = (int)(ndev->board->slot_addr+DAYNA_8390_MEM);
291                 dev->mem_end = dev->mem_start+DAYNA_MEMSIZE; /* 8K it seems */
292         
293                 printk(KERN_INFO "%s: daynaport. testing board: ", dev->name);
294                         
295                 printk("memory - ");    
296                         
297                 i = (void *)dev->mem_start;
298                 memset((void *)i,0xAA, DAYNA_MEMSIZE);
299                 while(i<(volatile unsigned short *)dev->mem_end)
300                 {
301                         if(*i!=0xAAAA)
302                                 goto membad;
303                         *i=0x5678; /* make sure we catch byte smearing */
304                         if(*i!=0x5678)
305                                 goto membad;
306                         i+=2;   /* Skip a word */
307                 }
308                         
309                 printk("controller - ");
310                         
311                 p=(void *)dev->base_addr;
312                 plen=0;
313                         
314                 while(plen<0x3FF00)
315                 {
316                         if(test_8390(p,0)==0)
317                                 break;
318                         if(test_8390(p,1)==0)
319                                 break;
320                         if(test_8390(p,2)==0)
321                                 break;
322                         if(test_8390(p,3)==0)
323                                 break;
324                         plen++;
325                         p++;
326                 }
327                 if(plen==0x3FF00)
328                         goto membad;
329                 printk("OK\n");
330                 dev->irq = SLOT2IRQ(ndev->board->slot);
331                 if(ns8390_probe1(dev, 0, "dayna", id, -1, ndev)==0)
332                         return 0;
333         }
334         /* Cabletron */
335         if (id==NS8390_CABLETRON) {
336                 int memsize = 16<<10; /* fix this */
337                   
338                 dev->base_addr=(int)(ndev->board->slot_addr+CABLETRON_8390_BASE);
339                 dev->mem_start=(int)(ndev->board->slot_addr+CABLETRON_8390_MEM);
340                 dev->mem_end=dev->mem_start+memsize;
341                 dev->irq = SLOT2IRQ(ndev->board->slot);
342                   
343                 /* The base address is unreadable if 0x00 has been written to the command register */
344                 /* Reset the chip by writing E8390_NODMA+E8390_PAGE0+E8390_STOP just to be sure */
345                 i = (void *)dev->base_addr;
346                 *i = 0x21;
347                   
348                 printk(KERN_INFO "%s: cabletron: testing board: ", dev->name);
349                 printk("%dK memory - ", memsize>>10);           
350                 i=(void *)dev->mem_start;
351                 while(i<(volatile unsigned short *)(dev->mem_start+memsize))
352                 {
353                         *i=0xAAAA;
354                         if(*i!=0xAAAA)
355                                 goto membad;
356                         *i=0x5555;
357                         if(*i!=0x5555)
358                                 goto membad;
359                         i+=2;   /* Skip a word */
360                 }
361                 printk("OK\n");
362                   
363                 if(ns8390_probe1(dev, 1, "cabletron", id, -1, ndev)==0)
364                         return 0;
365         }
366         /* Apple, Farallon, Asante */
367         if(id==NS8390_APPLE || id==NS8390_FARALLON || id==NS8390_ASANTE)
368         {
369                 int memsize;
370                         
371                 dev->base_addr=(int)(ndev->board->slot_addr+APPLE_8390_BASE);
372                 dev->mem_start=(int)(ndev->board->slot_addr+APPLE_8390_MEM);
373                         
374                 memsize = apple_8390_mem_probe((void *)dev->mem_start);
375                         
376                 dev->mem_end=dev->mem_start+memsize;
377                 dev->irq = SLOT2IRQ(ndev->board->slot);
378                         
379                 switch(id)
380                 {
381                 case NS8390_FARALLON:
382                         printk(KERN_INFO "%s: farallon: testing board: ", dev->name);
383                         break;
384                 case NS8390_ASANTE:
385                         printk(KERN_INFO "%s: asante: testing board: ", dev->name);
386                         break;
387                 case NS8390_APPLE:
388                 default:
389                         printk(KERN_INFO "%s: apple/clone: testing board: ", dev->name);
390                         break;
391                 }
392                         
393                 printk("%dK memory - ", memsize>>10);           
394                         
395                 i=(void *)dev->mem_start;
396                 memset((void *)i,0xAA, memsize);
397                 while(i<(volatile unsigned short *)dev->mem_end)
398                 {
399                         if(*i!=0xAAAA)
400                                 goto membad;
401                         *i=0x5555;
402                         if(*i!=0x5555)
403                                 goto membad;
404                         i+=2;   /* Skip a word */
405                 }
406                 printk("OK\n");
407                         
408                 switch (id)
409                 {
410                 case NS8390_FARALLON:
411                         if(ns8390_probe1(dev, 1, "farallon", id, -1, ndev)==0)
412                                 return 0;
413                         break;
414                 case NS8390_ASANTE:
415                         if(ns8390_probe1(dev, 1, "asante", id, -1, ndev)==0)
416                                 return 0;
417                         break;
418                 case NS8390_APPLE:
419                 default:
420                         if(ns8390_probe1(dev, 1, "apple/clone", id, -1, ndev)==0)
421                                 return 0;
422                         break;
423                 }
424         }
425         /* Interlan */
426         if(id==NS8390_INTERLAN)
427         {
428                 /* As apple and asante */
429                 dev->base_addr=(int)(ndev->board->slot_addr+APPLE_8390_BASE);
430                 dev->mem_start=(int)(ndev->board->slot_addr+APPLE_8390_MEM);
431                 dev->mem_end=dev->mem_start+APPLE_MEMSIZE; /* 8K it seems */
432                 dev->irq = SLOT2IRQ(ndev->board->slot);
433                 if(ns8390_probe1(dev, 1, "interlan", id, -1, ndev)==0)
434                         return 0;
435         }
436         /* Kinetics (Shiva Etherport) */
437         if(id==NS8390_KINETICS)
438         {
439                 dev->base_addr=(int)(ndev->board->slot_addr+KINETICS_8390_BASE);
440                 dev->mem_start=(int)(ndev->board->slot_addr+KINETICS_8390_MEM);
441                 dev->mem_end=dev->mem_start+KINETICS_MEMSIZE; /* 8K it seems */
442                 dev->irq = SLOT2IRQ(ndev->board->slot);
443                 if(ns8390_probe1(dev, 0, "kinetics", id, -1, ndev)==0)
444                         return 0;
445         }
446 
447         /* We should hopefully not get here */
448         printk(KERN_ERR "Probe unsucessful.\n");
449         return -ENODEV;
450 
451  membad:
452         printk(KERN_ERR "failed at %p in %p - %p.\n", i,
453                    (void *)dev->mem_start, (void *)dev->mem_end);
454         return -ENODEV;
455 }
456 
457 int __init mac8390_ethernet_addr(struct nubus_dev* ndev, 
458                                  unsigned char addr[6])
459 {
460         struct nubus_dir dir;
461         struct nubus_dirent ent;
462 
463         /* Get the functional resource for this device */
464         if (nubus_get_func_dir(ndev, &dir) == -1)
465                 return -1;
466         if (nubus_find_rsrc(&dir, NUBUS_RESID_MAC_ADDRESS, &ent) == -1)
467                 return -1;
468         
469         nubus_get_rsrc_mem(addr, &ent, 6);
470         return 0;
471 }
472 
473 int __init ns8390_probe1(struct net_device *dev, int word16, char *model_name,
474                          int type, int promoff, struct nubus_dev *ndev)
475 {
476         static u32 fwrd4_offsets[16]={
477                 0,      4,      8,      12,
478                 16,     20,     24,     28,
479                 32,     36,     40,     44,
480                 48,     52,     56,     60
481         };
482         static u32 back4_offsets[16]={
483                 60,     56,     52,     48,
484                 44,     40,     36,     32,
485                 28,     24,     20,     16,
486                 12,     8,      4,      0
487         };
488         static u32 fwrd2_offsets[16]={
489                 0,      2,      4,      6,
490                 8,     10,     12,     14,
491                 16,    18,     20,     22,
492                 24,    26,     28,     30
493         };
494 
495         unsigned char *prom = (unsigned char*) ndev->board->slot_addr + promoff;
496 
497         /* Allocate dev->priv and fill in 8390 specific dev fields. */
498         if (ethdev_init(dev)) 
499         {       
500                 printk ("%s: unable to get memory for dev->priv.\n", dev->name);
501                 return -ENOMEM;
502         }
503 
504         /* OK, we are certain this is going to work.  Setup the device. */
505 
506         ei_status.name = model_name;
507         ei_status.word16 = word16;
508 
509        if (type==NS8390_CABLETRON) {
510                /* Cabletron card puts the RX buffer before the TX buffer */
511                ei_status.tx_start_page = CABLETRON_TX_START_PG;
512                ei_status.rx_start_page = CABLETRON_RX_START_PG;
513                ei_status.stop_page = CABLETRON_RX_STOP_PG;
514                dev->rmem_start = dev->mem_start;
515                dev->rmem_end = dev->mem_start + CABLETRON_RX_STOP_PG*256;
516        } else {
517                ei_status.tx_start_page = WD_START_PG;
518                ei_status.rx_start_page = WD_START_PG + TX_PAGES;
519                ei_status.stop_page = (dev->mem_end - dev->mem_start)/256;
520                dev->rmem_start = dev->mem_start + TX_PAGES*256;
521                dev->rmem_end = dev->mem_end;
522        }
523         
524         if(promoff==-1)         /* Use nubus resources ? */
525         {
526                 if(mac8390_ethernet_addr(ndev, dev->dev_addr))
527                 {
528                   printk("mac_ns8390: MAC address not in resources!\n");
529                   return -ENODEV;
530                 }
531         }
532         else                    /* Pull it off the card */
533         {
534                 int i=0;
535                 int x=1;
536                 /* These should go in the end I hope */
537                 if(type==NS8390_DAYNA)
538                         x=2;
539                 if(type==NS8390_INTERLAN || type==NS8390_KINETICS)
540                         x=4;
541                 while(i<6)
542                 {
543                         dev->dev_addr[i]=*prom;
544                         prom+=x;
545                         if(i)
546                                 printk(":");
547                         printk("%02X",dev->dev_addr[i++]);
548                 }
549         }
550 
551         printk(KERN_INFO "%s: %s in slot %X (type %s)\n",
552                    dev->name, ndev->board->name, ndev->board->slot, model_name);
553         printk(KERN_INFO "MAC ");
554         {
555                 int i;
556                 for (i = 0; i < 6; i++) {
557                         printk("%2.2x", dev->dev_addr[i]);
558                         if (i < 5)
559                                 printk(":");
560                 }
561         }
562         printk(" IRQ %d, shared memory at %#lx-%#lx.\n",
563                    dev->irq, dev->mem_start, dev->mem_end-1);
564 
565         switch(type)
566         {
567                 case NS8390_DAYNA:      /* Dayna card */
568                 case NS8390_KINETICS:   /* Kinetics --  8 bit config, but 16 bit mem */
569                         /* 16 bit, 4 word offsets */
570                         ei_status.reset_8390 = &ns8390_no_reset;
571                         ei_status.block_input = &dayna_block_input;
572                         ei_status.block_output = &dayna_block_output;
573                         ei_status.get_8390_hdr = &dayna_get_8390_hdr;
574                         ei_status.reg_offset = fwrd4_offsets;
575                         break;
576                 case NS8390_CABLETRON: /* Cabletron */
577                         /*              16 bit card, register map is short forward */
578                         ei_status.reset_8390 = &ns8390_no_reset;
579                         /* Ctron card won't accept 32bit values read or written to it */
580                         ei_status.block_input = &slow_sane_block_input;
581                         ei_status.block_output = &slow_sane_block_output;
582                         ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
583                         ei_status.reg_offset = fwrd2_offsets;
584                         break;
585                 case NS8390_FARALLON:
586                 case NS8390_APPLE:      /* Apple/Asante/Farallon */
587                         /*      16 bit card, register map is reversed */
588                         ei_status.reset_8390 = &ns8390_no_reset;
589                         ei_status.block_input = &slow_sane_block_input;
590                         ei_status.block_output = &slow_sane_block_output;
591                         ei_status.get_8390_hdr = &slow_sane_get_8390_hdr;
592                         ei_status.reg_offset = back4_offsets;
593                         break;
594                 case NS8390_ASANTE:
595                         /*      16 bit card, register map is reversed */
596                         ei_status.reset_8390 = &ns8390_no_reset;
597                         ei_status.block_input = &sane_block_input;
598                         ei_status.block_output = &sane_block_output;
599                         ei_status.get_8390_hdr = &sane_get_8390_hdr;
600                         ei_status.reg_offset = back4_offsets;
601                         break;
602                 case NS8390_INTERLAN:   /* Interlan */
603                         /*      16 bit card, map is forward */
604                         ei_status.reset_8390 = &interlan_reset;
605                         ei_status.block_input = &sane_block_input;
606                         ei_status.block_output = &sane_block_output;
607                         ei_status.get_8390_hdr = &sane_get_8390_hdr;
608                         ei_status.reg_offset = back4_offsets;
609                         break;
610 #if 0 /* i think this suffered code rot.  my kinetics card has much
611            * different settings.  -- CSA [22-May-1999] */
612                 case NS8390_KINETICS:   /* Kinetics */
613                         /*      8bit card, map is forward */
614                         ei_status.reset_8390 = &ns8390_no_reset;
615                         ei_status.block_input = &sane_block_input;
616                         ei_status.block_output = &sane_block_output;
617                         ei_status.get_8390_hdr = &sane_get_8390_hdr;
618                         ei_status.reg_offset = back4_offsets;
619                         break;
620 #endif
621                 default:
622                         panic("Detected a card I can't drive - whoops\n");
623         }
624         dev->open = &ns8390_open;
625         dev->stop = &ns8390_close_card;
626 
627         NS8390_init(dev, 0);
628 
629         return 0;
630 }
631 
632 static int ns8390_open(struct net_device *dev)
633 {
634         MOD_INC_USE_COUNT;
635         ei_open(dev);
636 
637         /* At least on my card (a Focus Enhancements PDS card) I start */
638         /* getting interrupts right away, so the driver needs to be    */
639         /* completely initialized before enabling the interrupt.        */
640         /*                             - funaho@jurai.org (1999-05-17) */
641 
642         /* Non-slow interrupt, works around issues with the SONIC driver */
643         if (request_irq(dev->irq, ei_interrupt, 0, "8390 Ethernet", dev)) 
644         {
645                 printk ("%s: unable to get IRQ %d.\n", dev->name, dev->irq);
646                 MOD_DEC_USE_COUNT;
647                 return -EAGAIN;
648         }
649         return 0;
650 }
651 
652 static void ns8390_no_reset(struct net_device *dev)
653 {
654         if (ei_debug > 1) 
655                 printk("Need to reset the NS8390 t=%lu...", jiffies);
656         ei_status.txing = 0;
657         if (ei_debug > 1) printk("reset not supported\n");
658         return;
659 }
660 
661 static int ns8390_close_card(struct net_device *dev)
662 {
663         if (ei_debug > 1)
664                 printk("%s: Shutting down ethercard.\n", dev->name);
665         free_irq(dev->irq, dev);
666         ei_close(dev);
667         MOD_DEC_USE_COUNT;
668         return 0;
669 }
670 
671 /*
672  *    Interlan Specific Code Starts Here
673  */
674 
675 static void interlan_reset(struct net_device *dev)
676 {
677         unsigned char *target=nubus_slot_addr(IRQ2SLOT(dev->irq));
678         if (ei_debug > 1) 
679                 printk("Need to reset the NS8390 t=%lu...", jiffies);
680         ei_status.txing = 0;
681         /* This write resets the card */
682         target[0xC0000]=0;
683         if (ei_debug > 1) printk("reset complete\n");
684         return;
685 }
686 
687 /*
688  *    Daynaport code (some is used by other drivers)
689  */
690 
691 
692 /* Grab the 8390 specific header. Similar to the block_input routine, but
693    we don't need to be concerned with ring wrap as the header will be at
694    the start of a page, so we optimize accordingly. */
695 
696 
697 /* Block input and output are easy on shared memory ethercards, and trivial
698    on the Daynaport card where there is no choice of how to do it.
699    The only complications are that the ring buffer wraps.
700 */
701 
702 static void dayna_memcpy_fromcard(struct net_device *dev, void *to, int from, int count)
703 {
704         volatile unsigned short *ptr;
705         unsigned short *target=to;
706         from<<=1;       /* word, skip overhead */
707         ptr=(unsigned short *)(dev->mem_start+from);
708         /*
709          * Leading byte?
710          */
711         if (from&2) {
712                 *((char *)target)++ = *(((char *)ptr++)-1);
713                 count--;
714         }
715         while(count>=2)
716         {
717                 *target++=*ptr++;       /* Copy and */
718                 ptr++;                  /* skip cruft */
719                 count-=2;
720         }
721         /*
722          *      Trailing byte ?
723          */
724         if(count)
725         {
726                 /* Big endian */
727                 unsigned short v=*ptr;
728                 *((char *)target)=v>>8;
729         }
730 }
731 
732 static void dayna_memcpy_tocard(struct net_device *dev, int to, const void *from, int count)
733 {
734         volatile unsigned short *ptr;
735         const unsigned short *src=from;
736         to<<=1; /* word, skip overhead */
737         ptr=(unsigned short *)(dev->mem_start+to);
738         /*
739          * Leading byte?
740          */
741         if (to&2) { /* avoid a byte write (stomps on other data) */
742                 ptr[-1] = (ptr[-1]&0xFF00)|*((unsigned char *)src)++;
743                 ptr++;
744                 count--;
745         }
746         while(count>=2)
747         {
748                 *ptr++=*src++;          /* Copy and */
749                 ptr++;                  /* skip cruft */
750                 count-=2;
751         }
752         /*
753          *      Trailing byte ?
754          */
755         if(count)
756         {
757                 /* Big endian */
758                 unsigned short v=*src;
759                 /* card doesn't like byte writes */
760                 *ptr=(*ptr&0x00FF)|(v&0xFF00);
761         }
762 }
763 
764 static void dayna_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
765 {
766         unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
767         dayna_memcpy_fromcard(dev, (void *)hdr, hdr_start, 4);
768         /* Register endianism - fix here rather than 8390.c */
769         hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
770 }
771 
772 static void dayna_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
773 {
774         unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
775         unsigned long xfer_start = xfer_base+dev->mem_start;
776 
777         /*
778          *      Note the offset maths is done in card memory space which
779          *      is word per long onto our space.
780          */
781          
782         if (xfer_start + count > dev->rmem_end) 
783         {
784                 /* We must wrap the input move. */
785                 int semi_count = dev->rmem_end - xfer_start;
786                 dayna_memcpy_fromcard(dev, skb->data, xfer_base, semi_count);
787                 count -= semi_count;
788                 dayna_memcpy_fromcard(dev, skb->data + semi_count, 
789                         dev->rmem_start - dev->mem_start, count);
790         }
791         else
792         {
793                 dayna_memcpy_fromcard(dev, skb->data, xfer_base, count);
794         }
795 }
796 
797 static void dayna_block_output(struct net_device *dev, int count, const unsigned char *buf,
798                                 int start_page)
799 {
800         long shmem = (start_page - WD_START_PG)<<8;
801         
802         dayna_memcpy_tocard(dev, shmem, buf, count);
803 }
804 
805 /*
806  *      Cards with full width memory
807  */
808 
809 
810 static void sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
811 {
812         unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
813         memcpy((void *)hdr, (char *)dev->mem_start+hdr_start, 4);
814         /* Register endianism - fix here rather than 8390.c */
815         hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
816 }
817 
818 static void sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
819 {
820         unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
821         unsigned long xfer_start = xfer_base+dev->mem_start;
822 
823         if (xfer_start + count > dev->rmem_end) 
824         {
825                 /* We must wrap the input move. */
826                 int semi_count = dev->rmem_end - xfer_start;
827                 memcpy(skb->data, (char *)dev->mem_start+xfer_base, semi_count);
828                 count -= semi_count;
829                 memcpy(skb->data + semi_count, 
830                         (char *)dev->rmem_start, count);
831         }
832         else
833         {
834                 memcpy(skb->data, (char *)dev->mem_start+xfer_base, count);
835         }
836 }
837 
838 
839 static void sane_block_output(struct net_device *dev, int count, const unsigned char *buf,
840                                 int start_page)
841 {
842         long shmem = (start_page - WD_START_PG)<<8;
843         
844         memcpy((char *)dev->mem_start+shmem, buf, count);
845 }
846 
847 static void word_memcpy_tocard(void *tp, const void *fp, int count)
848 {
849         volatile unsigned short *to = tp;
850         const unsigned short *from = fp;
851         
852         count++;
853         count/=2;
854         
855         while(count--)
856                 *to++=*from++;
857 }
858 
859 static void word_memcpy_fromcard(void *tp, const void *fp, int count)
860 {
861         unsigned short *to = tp;
862         const volatile unsigned short *from = fp;
863         
864         count++;
865         count/=2;
866         
867         while(count--)
868                 *to++=*from++;
869 }
870 
871 static void slow_sane_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
872 {
873         unsigned long hdr_start = (ring_page - WD_START_PG)<<8;
874         word_memcpy_fromcard((void *)hdr, (char *)dev->mem_start+hdr_start, 4);
875         /* Register endianism - fix here rather than 8390.c */
876         hdr->count=(hdr->count&0xFF)<<8|(hdr->count>>8);
877 }
878 
879 static void slow_sane_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
880 {
881         unsigned long xfer_base = ring_offset - (WD_START_PG<<8);
882         unsigned long xfer_start = xfer_base+dev->mem_start;
883 
884         if (xfer_start + count > dev->rmem_end) 
885         {
886                 /* We must wrap the input move. */
887                 int semi_count = dev->rmem_end - xfer_start;
888                 word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, semi_count);
889                 count -= semi_count;
890                 word_memcpy_fromcard(skb->data + semi_count, 
891                         (char *)dev->rmem_start, count);
892         }
893         else
894         {
895                 word_memcpy_fromcard(skb->data, (char *)dev->mem_start+xfer_base, count);
896         }
897 }
898 
899 static void slow_sane_block_output(struct net_device *dev, int count, const unsigned char *buf,
900                                 int start_page)
901 {
902         long shmem = (start_page - WD_START_PG)<<8;
903         
904         word_memcpy_tocard((char *)dev->mem_start+shmem, buf, count);
905 #if 0
906         long shmem = (start_page - WD_START_PG)<<8;
907         volatile unsigned short *to=(unsigned short *)(dev->mem_start+shmem);
908         volatile int p;
909         unsigned short *bp=(unsigned short *)buf;
910         
911         count=(count+1)/2;
912         
913         while(count--)
914         {
915                 *to++=*bp++;
916                 for(p=0;p<10;p++)
917                         p++;
918         }
919 #endif  
920 }
921 
922 /*
923  * Local variables:
924  *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c daynaport.c"
925  *  version-control: t
926  *  c-basic-offset: 4
927  *  tab-width: 4
928  *  kept-new-versions: 5
929  * End:
930  */
931 

~ [ 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.