Subversion Repositories shark

Rev

Rev 927 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
629 giacomo 1
/*
2
 * Project: S.Ha.R.K.
3
 *
4
 * Coordinators:
5
 *   Giorgio Buttazzo    <giorgio@sssup.it>
6
 *   Paolo Gai           <pj@gandalf.sssup.it>
7
 *
8
 * Authors     :
9
 *   Paolo Gai           <pj@gandalf.sssup.it>
10
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
11
 *   Luca Abeni          <luca@gandalf.sssup.it>
12
 *   (see the web pages for full authors list)
13
 *
14
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
15
 *
16
 * http://www.sssup.it
17
 * http://retis.sssup.it
18
 * http://shark.sssup.it
19
 */
20
 
21
/**
22
 ------------
966 pj 23
 CVS :        $Id: eth.c,v 1.12 2005-02-25 11:04:03 pj Exp $
629 giacomo 24
 
25
 File:        $File$
966 pj 26
 Revision:    $Revision: 1.12 $
27
 Last update: $Date: 2005-02-25 11:04:03 $
629 giacomo 28
 ------------
29
**/
30
 
31
/*
32
 * Copyright (C) 2000 Luca Abeni
33
 *
34
 * This program is free software; you can redistribute it and/or modify
35
 * it under the terms of the GNU General Public License as published by
36
 * the Free Software Foundation; either version 2 of the License, or
37
 * (at your option) any later version.
38
 *
39
 * This program is distributed in the hope that it will be useful,
40
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
41
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
42
 * GNU General Public License for more details.
43
 *
44
 * You should have received a copy of the GNU General Public License
45
 * along with this program; if not, write to the Free Software
46
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
47
 *
48
 */
49
 
50
 
51
/* Author:      Luca Abeni                  */
52
/* Date:        2/12/1997                                       */
53
 
54
/* File:    eth.C                       */
55
/* Revision:    2.0                     */
56
 
57
/*
58
   Ethernet layer: it is an inetrface between the low level driver (
59
   3Com 3c59xx, ...) and the high level protocols (IP, ARP,...).
60
*/
61
 
62
/* only 4 debug... */
63
int netlev;
64
 
65
#include <kernel/kern.h>
966 pj 66
#include <hartport/hartport/hartport.h>
629 giacomo 67
 
636 giacomo 68
#include <linux/pci.h>
629 giacomo 69
 
70
#include "eth_priv.h"
71
#include "netbuff.h"
72
 
73
#include <linux/netdevice.h>
74
/*#include "lowlev.h"
75
//#include "3com.h" */
76
 
77
//#define DEBUG_ETH
78
 
79
#define ETH_PAGE        5
80
 
81
struct eth_service{
82
        WORD type;
83
        void (*rfun)(void *pkt);
84
} ETH_SERVICE;
85
 
86
int definedprotocols;
87
struct eth_service eth_table[ETH_MAX_PROTOCOLS];
88
 
89
#define ETH_RX_BUFFERS      4   
90
#define ETH_TX_BUFFERS      4
91
 
92
#ifndef ETH0_ADDR
93
# define ETH0_ADDR 0
94
#endif
95
#ifndef ETH0_IRQ
96
# define ETH0_IRQ 0
97
#endif
98
 
99
#define NONE 0
100
 
101
/*extern void net_handler(void);
102
//extern PID net_extern_driver(void);*/
103
 
104
PID nettask_pid = NIL;
105
static PORT NetRxPort;
106
 
107
/* void (*vortex_send)(DWORD BaseAddress, DWORD *txbuff, int len); */
108
 
109
int ethIsInstalled = FALSE;
110
 
111
/* device descriptor */
112
struct eth_device eth_dev;
113
struct pci_des pci_devs[5];
114
/* This is the Linux one!!! */
115
static struct device device0 = {
116
        "eth0", 0, 0, 0, 0, ETH0_ADDR, ETH0_IRQ, 0, 0, 0, NULL, NULL};
117
struct device *dev_base = &device0;
118
 
119
/* received frames buffers */
120
extern struct netbuff rxbuff; /* from skbuff.c */
121
 
122
/* buffers for the frames to send */
123
/* struct netbuff txbuff; */
124
 
125
/* Called if an unknown frames arrives */
126
void eth_nullfun(void *pkt)
127
{
128
        kern_raise(ETH_NULLPROTOCOL_EXC,NIL);
129
}
130
 
131
void dev_tint(struct device *dev)
132
{
133
        printk(KERN_WARNING "Warning! dev_tint called. (Why?)\n");
927 pj 134
        exit(201);
629 giacomo 135
}
136
 
137
/*
138
   -----------------------------------------------------------------------
139
   The extern process calls this function when a frame arrives
140
   -----------------------------------------------------------------------
141
*/
142
 
143
void netif_rx(struct sk_buff *skb)
144
{
145
        // cprintf("DENTRO netif_rx, skbuf=%p\n",skb->data);
146
        if (nettask_pid == NIL) {
147
                printk(KERN_CRIT "Net receives packets, but the driver doesn't exist.\n");
927 pj 148
                exit(300);
629 giacomo 149
        }
150
 
151
        port_send(NetRxPort,skb,NON_BLOCK);
152
        // task_activate(nettask_pid);
153
}
154
 
155
TASK net_extern_driver(void)
156
{
157
        static PORT NetPort;
158
        struct sk_buff skb;
159
        void *pkt;
160
        int len;
161
        BYTE count;
162
        int i;
163
 
164
        NetPort = port_connect("NetPort", sizeof(struct sk_buff), STREAM, READ);
165
        while (1) {
166
                /* debug... */
167
                netlev = 1;
168
 
169
                port_receive(NetPort,&skb,BLOCK);  
170
                pkt = skb.data;
171
                len = skb.len;
172
 
173
                ((struct eth_header *)pkt)->type = ntohs(((struct eth_header *)pkt)->type);
174
                count = 0;
175
                /* Search for the frame protocol...*/
176
                for (i = 0; i < definedprotocols; i++) {
177
                        /* debug... */
178
                        netlev = 10 + i;
179
 
180
                        if (eth_table[i].type == (((struct eth_header *)pkt)->type)) {
181
                                count++;
182
                                /*...and call the protocol CallBack!!! */
183
                                eth_table[i].rfun(pkt);
184
                        }
185
                }
186
 
187
                /* debug... */
188
                netlev = 20;
189
 
190
                // cprintf("ETH: releasing %p\n", pkt);
191
 
192
                // NOTE changed by PJ because skb.data not always point to the
193
                // buffer start!!!... it is skb.head that always points there!
194
                netbuff_release(&rxbuff, skb.head);
195
 
196
                /* debug... */
197
                netlev = 30;
198
        }
199
}
200
 
201
/*
202
   --------------------
203
   Interface functions
204
   --------------------
205
*/
206
/* formatted print of an ethernet header */
207
void eth_printHeader(struct eth_header *p)
208
{
209
        cprintf("Dest   : %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n",p->dest.ad[0],
210
                                                        p->dest.ad[1],
211
                                                        p->dest.ad[2],
212
                                                        p->dest.ad[3],
213
                                                        p->dest.ad[4],
214
                                                        p->dest.ad[5]);
215
        cprintf("Source : %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x \n",p->source.ad[0],
216
                                                        p->source.ad[1],
217
                                                        p->source.ad[2],
218
                                                        p->source.ad[3],
219
                                                        p->source.ad[4],
220
                                                        p->source.ad[5]);
221
        cprintf("Type : %x\n",p->type);
222
}
223
 
224
void eth_showinfo(struct eth_device *d)
225
{
226
        cprintf("IntLine                : %d\n",d->IntLine);
227
        cprintf("BaseAddress    : %lx\n",d->BaseAddress);
228
        cprintf("Address                : %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
229
                                        d->addr.ad[0],d->addr.ad[1],d->addr.ad[2],
230
                                        d->addr.ad[3],d->addr.ad[4],d->addr.ad[5]);
231
}
232
 
233
/* formatted print of an ethernet frame*/
234
void eth_printPkt(char *pkt,int len)
235
{
236
        int i,j,offset;
237
 
238
        eth_printHeader((struct eth_header *)pkt);
239
        offset = sizeof(struct eth_header);
240
        len -= offset;
241
        for (i = 0; i < len; i += 10) {
242
        for (j = 0; j < 10; j++)
243
                cprintf("%2.2x  ", pkt[offset+i+j]);
244
        for (j = 0; j < 10; j++)
245
                cputc(pkt[offset+i+j]);
246
                cprintf("\n");
247
        }
248
        cprintf("\n");
249
}
250
 
251
void eth_copy_and_sum(struct sk_buff *dest, unsigned char *src, int length, int base)
252
{
253
        memcpy(dest->data, src, length);
254
}
255
 
256
#if 0                                                                   
257
/*-------------------- User Interface -----------------------------*/
258
unsigned short htons(unsigned short host)
259
{
260
        return ((host & 0xff00) >> 8) + ((host & 0x00ff) << 8);
261
}
262
 
263
unsigned short ntohs(unsigned short host)
264
{
265
        return ((host & 0xff00) >> 8) + ((host & 0x00ff) << 8);
266
}
267
#endif
268
 
269
/*
270
   Translate an ethernet address from a text string to an eth_addr
271
   structure
272
*/
273
void eth_str2Addr(char *add, struct eth_addr *ds)
274
{
275
        int ad[6];
276
        int i,j;
277
        char c;
278
 
279
        i = 0;
280
        for(j = 0; j < 6; j++) {
281
                ad[j] = 0;
282
                        while((add[i] != ':') && (add[i] != 0)) {
283
                                c = add[i++];
284
                                if (c <= '9') c = c - '0';
285
                                else c = c - 'A' + 10;
286
                                ad[j] = ad[j] * 16 + c;
287
                        }
288
                i++;
289
        }
290
        for (i=0; i<6; i++) ds->ad[i] = ad[i];
291
}
292
 
293
/* Set a higher level protocol's CallBack */
294
int eth_setProtocol(WORD type, void (*recv)(void *pkt))
295
{
296
        int i;
297
 
298
        if (definedprotocols == ETH_MAX_PROTOCOLS) return FALSE;
299
        for(i = 0; i < definedprotocols; i++) {
300
                if (eth_table[i].type == type) return FALSE;
301
        }
302
        eth_table[definedprotocols].type = type;
303
        eth_table[definedprotocols++].rfun = recv;
304
 
305
        return TRUE;
306
}
307
 
308
/* Fill an ethernet frame's header and return a pointer to the frame's body */
309
void *eth_setHeader(void *b,struct eth_addr dest, WORD type)
310
{
311
        setEthAddr(((struct eth_header *)b)->dest,dest);
312
        setEthAddr(((struct eth_header *)b)->source,eth_dev.addr);
313
        /* the type field is in big-endian format */
314
        ((struct eth_header *) b)->type = htons(type);
315
 
316
        return((BYTE *)b + sizeof(struct eth_header));
317
}
318
 
319
/* getFirstDataByte : Return a pointer to the body of an ethernet frame */
320
void *eth_getFDB(void *p)
321
{
322
        return ((void *)((BYTE *)p + sizeof(struct eth_header)));
323
}
324
 
325
/* eth_getAddress : return the local ethernet address */
326
void eth_getAddress(struct eth_addr *eth)
327
{
328
        memcpy(eth->ad,&(device0.dev_addr),sizeof(struct eth_addr));
329
}
330
 
331
/* Send an ethernet frame */
332
int eth_sendPkt(void *p, int len)
333
{
334
        int i;
335
        int l;
336
        struct sk_buff buff;
337
 
338
        l = len + sizeof(struct eth_header);
339
        if (l < 60) {
340
                for (i = l; i <= 60; i++) *((BYTE *)p + i) = 0;
341
                l = 60;
342
        }
343
        buff.len = l;
344
        buff.data = p;
345
        device0.hard_start_xmit(&buff, &device0);
346
        /* lowlev_send(eth_dev.BaseAddress, p, l); */
347
 
348
        return TRUE;
349
}
350
 
351
int eth_exc(int err)
352
{
353
        int p;
354
 
355
         if (err != ETH_BUFFERS_FULL) printk(KERN_ERR "Ethernet : ");
356
        switch (err) {
357
        case ETH_DRIVER_NOT_FOUND :
358
                printk(KERN_ERR "NET PANIC --> Etherlink not found.\n");
359
                return 0;
360
        case ETH_RXERROR :
361
                printk(KERN_ERR "Receive error.\n");
362
                return 0;
363
        case ETH_TXERROR :
364
                printk(KERN_ERR "Transimit error: N. Max Retry.\n");
365
                return 0;
366
        case ETH_PROTOCOL_ERROR :
367
                printk(KERN_ERR "Too much protocols.\n");
368
                return 0;
369
        case ETH_BUFFERS_FULL:
370
                printk(KERN_ERR "Buffers full: frame lost!\n");
371
                return 1;
372
        case ETH_NULLPROTOCOL_EXC:
373
                printk(KERN_ERR "Null protocol called!\n");
374
                for (p = 0; p < ETH_MAX_PROTOCOLS; p++) {
375
                printk(KERN_ERR "%d:   %d\n", p, eth_table[p].type);
376
                }
377
                return 0;
378
        default :
379
                return 1;
380
        }
381
}
382
 
383
void skb_init(void);
384
void linuxpci_init(void);
385
int rtl8139_probe(struct device *dev);
386
int tc59x_probe(struct device *dev);
387
int eepro100_probe(struct device *dev);
388
int el3_probe(struct device *dev);
389
int ne_probe(struct device *dev);
390
 
391
int eth_init(int mode, TASK_MODEL *m)
392
{
393
        SOFT_TASK_MODEL m_soft;
394
        int i;
395
#if 0
396
        ndev;
397
        WORD Class;
398
        struct pci_regs *r;
399
        PID p;
400
 
401
#endif
402
 
403
        BYTE cardtype;
404
        int linux_found = 0;
405
 
406
        if (!ethIsInstalled) {
407
                /* Scan the devices connected to the PCI bus */
408
                cardtype = NONE;
409
 
410
                skb_init();
411
                NetRxPort = port_create("NetPort",sizeof(struct sk_buff),50,STREAM,WRITE);
412
                if (!m) {
413
                        soft_task_default_model(m_soft);
414
                        soft_task_def_wcet(m_soft, 1000);
415
                        soft_task_def_period(m_soft,20000);
416
                        soft_task_def_met(m_soft, 1000);
417
                        soft_task_def_aperiodic(m_soft);
418
                        soft_task_def_system(m_soft);
419
                        soft_task_def_nokill(m_soft);
420
                        m = (TASK_MODEL *)&m_soft;
421
                }
422
 
423
                nettask_pid = task_create("rxProc", net_extern_driver, m, NULL);
424
                if (nettask_pid == NIL) {
425
                        printk(KERN_ERR "Can't create extern driver.\n");
426
                        return 0;
427
                }
428
                task_activate(nettask_pid);
429
 
430
                if (1) { //!!!if (pci_init() == 1) {
431
                        linuxpci_init();
432
#ifdef DEBUG_ETH
433
                        printk(KERN_DEBUG "LF %d\n", linux_found);
434
#endif
435
                        linux_found += (rtl8139_probe(&device0) == 0);
436
#ifdef DEBUG_ETH
437
                        printk(KERN_DEBUG "LF %d\n", linux_found);
438
#endif
439
                        linux_found += (tc59x_probe(&device0) == 0);
440
#ifdef DEBUG_ETH
441
                        printk(KERN_DEBUG "LF %d\n", linux_found);
442
#endif
443
                        linux_found += (eepro100_probe(&device0) == 0);
444
#ifdef DEBUG_ETH
445
                        printk(KERN_DEBUG "LF %d\n", linux_found);
446
#endif
447
 
448
 
449
#if 0
450
                ndev = pci_scan_bus(pci_devs);
451
#ifdef __ETH_DBG__
452
                pci_show(pci_devs, ndev);
453
#endif
454
                for (i = 0; i < ndev; i++) {
455
                r = (struct pci_regs *) pci_devs[i].mem;
456
                Class = r->ClassCode;
457
                /* Is there a network card? */
458
                if (Class == 0x0200) {
459
                        if (cardtype == NONE) {
460
                        cardtype = UNKNOWN;
461
                        }
462
                /* is it a 3COM card? */
463
                        if (r->VendorId == 0x10b7) {
464
                        /* YES!!!!!! */
465
                        lowlev_info = vortex_info;
466
                                lowlev_readregs = vortex_readregs;
467
                                lowlev_open = vortex_open;
468
                                lowlev_close = vortex_close;
469
                                if (mode == TXTASK) {
470
                                lowlev_send = vortex_send_msg;
471
                        } else {
472
                                lowlev_send = vortex_send_mem;
473
                        }
474
                        printk(KERN_INFO "PCI Ethlink card found:\n");
475
                        lowlev_info(r);
476
                        cardtype = VORTEX;
477
                        }
478
                }
479
                }
480
        }
481
        if ((cardtype == NONE) || (cardtype == UNKNOWN)) {
482
                exc_raise(ETH_DRIVER_NOT_FOUND);
483
        }
484
        /*PUT HERE THE PFUN INIT!!!*/
485
        if (cardtype == VORTEX) {
486
        }
487
        /*
488
           Use it if you want to see the value of the internal
489
           registers of the card
490
        */
491
        /*vortex_readregs(eth_dev.BaseAddress);*/
492
 
493
        p = lowlev_open(eth_dev.BaseAddress, mode);
494
 
495
        /* Set the Fast Handler and the external process */
496
        handler_set(eth_dev.IntLine, net_handler, p);
497
#else
498
                }
499
                if (linux_found == 0) {
500
                  linux_found += (el3_probe(&device0) == 0);
501
#ifdef DEBUG_ETH
502
                  printk(KERN_DEBUG "LF %d\n", linux_found);
503
#endif
504
                  linux_found += (ne_probe(&device0) == 0);
505
#ifdef DEBUG_ETH
506
                  printk(KERN_DEBUG "LF %d\n", linux_found);
507
#endif
508
                  linux_found += (NS8390_init(&device0, 1) == 0);
509
#ifdef DEBUG_ETH
510
                  printk(KERN_DEBUG "LF %d\n", linux_found);
511
#endif
512
                }
513
 
514
/*
515
                if (mode & LOOPBACK) {
516
                        cprintf("Installing loopback device (forced)\n");
517
                        loopback_init(&device0);
518
                }
519
*/
520
                if (linux_found) {
521
                        device0.open(&device0);
522
                        printk(KERN_INFO "Network card found.\n");
523
                } else {
524
                        printk(KERN_INFO "No network card found.\n");
525
/*                      cprintf("No network card found. Installing loopback device.\n");
526
                        loopback_init(&device0);
527
                        device0.open(&device0);*/
528
                        return 0;
529
                }
530
#endif
531
 
532
                //netbuff_init(&rxbuff, ETH_RX_BUFFERS, ETH_MAX_LEN);
533
                //netbuff_init(&txbuff, ETH_TX_BUFFERS, ETH_MAX_LEN);
534
 
535
                definedprotocols = 0;
536
                for (i = 0; i < ETH_MAX_PROTOCOLS; i++) {
537
                        eth_table[i].type = 0;
538
                        eth_table[i].rfun = eth_nullfun;
539
                }
540
                ethIsInstalled = TRUE;
541
                /* Don't crash the system at the exit, please :) */
542
                sys_atrunlevel(eth_close,NULL,RUNLEVEL_BEFORE_EXIT);
543
 
544
        } else {
545
                printk(KERN_INFO "Ethernet already installed.\n");
546
                return 0;
547
        }
548
        return 1;
549
}
550
 
551
void eth_close(void *a)
552
{
553
#ifdef DEBUG_ETH
554
        printk(KERN_DEBUG "Network Closing.\n");
555
#endif
556
        if (ethIsInstalled == TRUE) {
557
                device0.stop(&device0);
558
                /* This seems to break everithing... */
559
                // lowlev_close(eth_dev.BaseAddress);
560
                ethIsInstalled = FALSE;
561
        }
562
#ifdef DEBUG_ETH
563
        printk(KERN_DEBUG "Network Closed.\n");
564
#endif
565
}