Kernel 0.5.7-r7; new app imgshow for display bmp images, new app telnetd
[ZeXOS.git] / kernel / drivers / net / pcnet32 / pcnet32.c
blobc19d6a3bad0b758973fb9004c81eb17a49ce1395
1 /*
2 * ZeX/OS
3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@gmail.com)
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <config.h>
21 #ifdef CONFIG_DRV_PCNET32
23 #include <system.h>
24 #include <string.h>
25 #include <x86.h>
26 #include <pci.h>
27 #include <task.h>
28 #include <net/eth.h>
29 #include <net/net.h>
31 /* AMD Vendor ID */
32 #define AMD_VENDORID 0x1022
34 /* PCNet/Home Device IDs */
35 #define PCNET_DEVICEID 0x2000
37 /* I/O 32bit resources */
38 #define PCNET32_IO_APR 0x00
39 #define PCNET32_IO_RDP 0x10
40 #define PCNET32_IO_ADDR 0x12
41 #define PCNET32_IO_RAP 0x14
42 #define PCNET32_IO_RESET 0x18
43 #define PCNET32_IO_BDP 0x1C
45 /* Ring's sizes */
46 #define PCNET32_BUF_ENC_TX 0
47 #define PCNET32_BUF_ENC_RX 0
49 #define PCNET32_RING_TX_SIZE (1 << (PCNET32_BUF_ENC_TX))
50 #define PCNET32_RING_TX_LEN_BITS ((PCNET32_BUF_ENC_TX) << 12)
52 #define PCNET32_RING_RX_SIZE (1 << (PCNET32_BUF_ENC_RX))
53 #define PCNET32_RING_RX_LEN_BITS ((PCNET32_BUF_ENC_RX) << 4)
55 #define PCNET32_RING_TX_BUF_LEN 1024
56 #define PCNET32_RING_RX_BUF_LEN 2048
58 /* Ring entries state */
59 #define PCNET32_FLAG_RX_OWN 0x8000
61 /* CSR port definition */
62 #define PCNET32_CSR_STATUS 0x0
64 /* BCR port definition */
65 #define PCNET32_BCR_BUSCTL 0x12
66 #define PCNET32_BCR_SWMODE 0x14
68 /* PCNnet32 CSR status */
69 #define PCNET32_STATUS_ERR 0x8000
70 #define PCNET32_STATUS_BABL 0x4000
71 #define PCNET32_STATUS_CERR 0x2000
72 #define PCNET32_STATUS_MISS 0x1000
73 #define PCNET32_STATUS_MERR 0x800
74 #define PCNET32_STATUS_RINT 0x400
75 #define PCNET32_STATUS_TINT 0x200
76 #define PCNET32_STATUS_IDON 0x100
77 #define PCNET32_STATUS_INTR 0x80
78 #define PCNET32_STATUS_IENA 0x40
79 #define PCNET32_STATUS_RXON 0x20
80 #define PCNET32_STATUS_TXON 0x10
81 #define PCNET32_STATUS_TDMD 0x8
82 #define PCNET32_STATUS_STOP 0x4
83 #define PCNET32_STATUS_START 0x2
84 #define PCNET32_STATUS_INIT 0x1
86 /* Interrupt status definition */
87 #define PCNET32_INT_RST 0x0000
88 #define PCNET32_INT_WINT 0x0200
89 #define PCNET32_INT_RINT 0x0400
90 #define PCNET32_INT_RERR 0x1000
91 #define PCNET32_INT_WERR 0x4000
92 #define PCNET32_INT_ERR 0x8000
94 static unsigned short pcnet32_ring_xlen[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512 };
96 /* init block structure */
97 struct pcnet32_init_t {
98 unsigned short mode; /* copied into csr15 */
99 unsigned short res1:4; /* reserved */
100 unsigned char rlen:1; /* number of receive descriptor ring entries */
101 unsigned char rlen2:1;
102 unsigned char rlen3:1;
103 unsigned char rlen4:1;
104 unsigned short res2:4; /* reserved */
105 unsigned short tlen:1; /* number of transmit descriptor ring entries */
106 unsigned short tlen2:1;
107 unsigned short tlen3:1;
108 unsigned short tlen4:1;
109 unsigned char padr[6]; /* mac address */
110 unsigned short res3; /* reserved */
111 unsigned short ladrf1; /* logical address filter 0..15 */
112 unsigned short ladrf2; /* logical address filter 16..31 */
113 unsigned short ladrf3; /* logibal address filter 32..47 */
114 unsigned short ladrf4; /* logical address filter 48..63 */
115 unsigned rdra; /* address of receive descriptor ring */
116 unsigned tdra; /* address of receive descriptor ring */
117 /* unsigned char res1:4;
118 unsigned char rlen:1;
119 unsigned char rlen2:1;
120 unsigned char rlen3:1;
121 unsigned char rlen4:1;
122 unsigned tdra:24; */ /* address of transmit descriptor ring */
123 /* unsigned char res2:4;
124 unsigned char tlen:1;
125 unsigned char tlen2:1;
126 unsigned char tlen3:1;
127 unsigned char tlen4:1;*/
130 /* rings structure */
131 /*struct pcnet32_ringtx_t {
132 unsigned buf;
133 unsigned status;
134 unsigned flags;
135 unsigned res;
136 };*/
138 /** Transmit Message Descriptor */
139 struct pcnet32_ringtx_t
141 struct
143 unsigned tbadr; /**< transmit buffer address */
144 } tmd0;
145 struct
147 unsigned bcnt:12; /**< buffer byte count (two's complement) */
148 unsigned ones:4; /**< must be 1111b */
149 unsigned res:7; /**< reserved */
150 unsigned bpe:1; /**< bus parity error */
151 unsigned enp:1; /**< end of packet */
152 unsigned stp:1; /**< start of packet */
153 unsigned def:1; /**< deferred */
154 unsigned one:1; /**< exactly one retry was needed to transmit a frame */
155 unsigned ltint:1; /**< suppress interrupts after successful transmission */
156 unsigned nofcs:1; /**< when set, the state of DXMTFCS is ignored and
157 transmitter FCS generation is activated. */
158 unsigned err:1; /**< error occured */
159 unsigned own:1; /**< 0=owned by guest driver, 1=owned by controller */
160 } tmd1;
161 struct
163 unsigned trc:4; /**< transmit retry count */
164 unsigned res:12; /**< reserved */
165 unsigned tdr:10; /**< ??? */
166 unsigned rtry:1; /**< retry error */
167 unsigned lcar:1; /**< loss of carrier */
168 unsigned lcol:1; /**< late collision */
169 unsigned exdef:1; /**< excessive deferral */
170 unsigned uflo:1; /**< underflow error */
171 unsigned buff:1; /**< out of buffers (ENP not found) */
172 } tmd2;
173 struct
175 unsigned res; /**< reserved for user defined space */
176 } tmd3;
179 /** Receive Message Descriptor */
180 struct pcnet32_ringrx_t {
181 struct
183 unsigned rbadr; /**< receive buffer address */
184 } rmd0;
185 struct
187 unsigned bcnt:12; /**< buffer byte count (two's complement) */
188 unsigned ones:4; /**< must be 1111b */
189 unsigned res:4; /**< reserved */
190 unsigned bam:1; /**< broadcast address match */
191 unsigned lafm:1; /**< logical filter address match */
192 unsigned pam:1; /**< physcial address match */
193 unsigned bpe:1; /**< bus parity error */
194 unsigned enp:1; /**< end of packet */
195 unsigned stp:1; /**< start of packet */
196 unsigned buff:1; /**< buffer error */
197 unsigned crc:1; /**< crc error on incoming frame */
198 unsigned oflo:1; /**< overflow error (lost all or part of incoming frame) */
199 unsigned fram:1; /**< frame error */
200 unsigned err:1; /**< error occured */
201 unsigned own:1; /**< 0=owned by guest driver, 1=owned by controller */
202 } rmd1;
203 struct
205 unsigned mcnt:12; /**< message byte count */
206 unsigned zeros:4; /**< 0000b */
207 unsigned rpc:8; /**< receive frame tag */
208 unsigned rcc:8; /**< receive frame tag + reserved */
209 } rmd2;
210 struct
212 unsigned res; /**< reserved for user defined space */
213 } rmd3;
216 /* pcnet32 device structure */
217 struct pcnet32_dev_t {
218 unsigned char irq;
219 pcidev_t *pcidev;
220 unsigned short addr_io;
221 mac_addr_t addr_mac;
224 struct pcnet32_dev_t *pcnet32_dev;
226 static void outl (unsigned short portno, unsigned long val) {
227 __asm__ __volatile__ ("outl %0, %w1" :: "a" (val), "Nd" (portno));
230 static unsigned long inl (unsigned short portno) {
231 unsigned long retval;
232 __asm__ __volatile__ ("inl %w1, %0" : "=a" (retval) : "Nd" (portno));
233 return retval;
236 /* I/O operations */
237 unsigned char pcnet32_read8 (struct pcnet32_dev_t *dev, unsigned short port)
239 return inb (dev->addr_io + port);
242 unsigned short pcnet32_read16 (struct pcnet32_dev_t *dev, unsigned short port)
244 return inw (dev->addr_io + port);
247 unsigned pcnet32_read32 (struct pcnet32_dev_t *dev, unsigned short port)
249 return inl (dev->addr_io + port);
252 void pcnet32_write32 (struct pcnet32_dev_t *dev, unsigned short port, unsigned val)
254 outl (dev->addr_io + port, val);
257 /* Register access */
258 unsigned pcnet32_read_csr (struct pcnet32_dev_t *dev, unsigned short reg)
260 pcnet32_write32 (dev, PCNET32_IO_RAP, reg);
261 return pcnet32_read32 (dev, PCNET32_IO_RDP);
264 void pcnet32_write_csr (struct pcnet32_dev_t *dev, unsigned short reg, unsigned short val)
266 pcnet32_write32 (dev, PCNET32_IO_RAP, reg);
267 pcnet32_write32 (dev, PCNET32_IO_RDP, val);
270 void pcnet32_write_bcr (struct pcnet32_dev_t *dev, unsigned short reg, unsigned short val)
272 pcnet32_write32 (dev, PCNET32_IO_RAP, reg);
273 pcnet32_write32 (dev, PCNET32_IO_BDP, val);
277 /* Prototype */
278 bool pcnet32_acthandler (unsigned act, char *block, unsigned block_len);
279 unsigned pcnet32_ring_create (struct pcnet32_dev_t *dev, struct pcnet32_init_t *iblock);
280 unsigned pcnet32_start (struct pcnet32_dev_t *dev);
281 void pcnet32_int ();
282 unsigned pcnet32_int_rx (struct pcnet32_dev_t *dev);
285 /* READ/WRITE func */
286 unsigned pcnet32_read (char *buf, unsigned len)
288 pcnet32_acthandler (DEV_ACT_READ, buf, len);
291 unsigned pcnet32_write (char *buf, unsigned len)
293 pcnet32_acthandler (DEV_ACT_WRITE, buf, len);
297 /* detect pcnet32 device in PC */
298 pcidev_t *pcnet32_detect ()
300 /* First detect network card - is connected to PCI bus ?*/
301 pcidev_t *pcidev = pcidev_find (AMD_VENDORID, PCNET_DEVICEID);
303 if (!pcidev)
304 return 0;
306 return pcidev;
309 /* INIT sequence */
310 unsigned init_pcnet32 ()
312 unsigned i = 0;
314 pcidev_t *pcidev = pcnet32_detect ();
316 if (!pcidev)
317 return 0;
319 struct pcnet32_dev_t *dev = (struct pcnet32_dev_t *) kmalloc (sizeof (struct pcnet32_dev_t));
321 if (!dev)
322 return 0;
324 /* get irq id */
325 dev->irq = pcidev->u.h0.interrupt_line;
326 dev->addr_io = pcidev->u.h0.base_registers[0];
328 // get mac address from ethernet
329 for (i = 0; i < 6; i++)
330 dev->addr_mac[i] = pcnet32_read8 (dev, i);
332 irq_install_handler (dev->irq, pcnet32_int);
334 pcnet32_dev = dev;
336 return pcnet32_start (dev);
338 unsigned init_block;
339 unsigned pcnet32_start (struct pcnet32_dev_t *dev)
341 struct pcnet32_init_t *iblock = (struct pcnet32_init_t *) 0x50000; // TODO: page aligned address
343 if (!iblock)
344 return 0;
346 int ret = pcnet32_ring_create (dev, iblock);
348 pcnet32_read32 (dev, PCNET32_IO_RESET);
349 pcnet32_write32 (dev, PCNET32_IO_RESET, 0);
351 outl (dev->addr_io + PCNET32_IO_RDP, 0);
352 pcnet32_write_bcr (dev, PCNET32_BCR_SWMODE, 0x0002);
355 iblock->mode = 0x0; // 0x8000 promiskuitni rezim
357 iblock->rlen = 0;
358 iblock->rlen2 = 0;
359 iblock->rlen3 = 0;
360 iblock->rlen4 = 0;
362 iblock->tlen = 0;
363 iblock->tlen2 = 0;
364 iblock->tlen3 = 0;
365 iblock->tlen4 = 0;
367 memcpy (iblock->padr, dev->addr_mac, 6);
369 iblock->ladrf1 = (unsigned short) ~0;
370 iblock->ladrf2 = (unsigned short) ~0;
371 iblock->ladrf3 = (unsigned short) ~0;
372 iblock->ladrf4 = (unsigned short) ~0;
374 kprintf ("init block: %d\n", sizeof (struct pcnet32_init_t));
375 kprintf ("rxring: 0x%x / txring: 0x%x\n", iblock->rdra, iblock->tdra);
377 out_word(ioaddr+LANCE_ADDR, 0x1);
378 (void)in_word(ioaddr+LANCE_ADDR);
380 out_word(ioaddr+LANCE_DATA, (short)l);
381 out_word(ioaddr+LANCE_ADDR, 0x2);
382 (void)in_word(ioaddr+LANCE_ADDR);
384 out_word(ioaddr+LANCE_DATA, (short)(l >> 16));
385 out_word(ioaddr+LANCE_ADDR, 0x4);
386 (void)in_word(ioaddr+LANCE_ADDR);
388 out_word(ioaddr+LANCE_DATA, 0x915);
389 out_word(ioaddr+LANCE_ADDR, 0x0);
390 (void)in_word(ioaddr+LANCE_ADDR);*/
392 /* ----- start when init done. ----- */
393 // out_word(ioaddr+LANCE_DATA, 0x4); /* stop */
394 // out_word(ioaddr+LANCE_DATA, 0x1); /* init */
397 //outw (dev->addr_io + PCNET32_IO_ADDR, 0x1);
398 //inw (dev->addr_io + PCNET32_IO_ADDR);
402 //outw (dev->addr_io + PCNET32_IO_RDP, 0x4);
403 //outw (dev->addr_io + PCNET32_IO_RDP, 0x1);
404 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, PCNET32_STATUS_STOP);
406 init_block = (unsigned) iblock;
408 pcnet32_write_csr (dev, 1, init_block);
409 pcnet32_write_csr (dev, 2, ((unsigned) init_block >> 16));
411 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, PCNET32_STATUS_INIT);
413 while (!(pcnet32_read_csr (dev, PCNET32_CSR_STATUS) & PCNET32_STATUS_IDON));
416 unsigned ring = pcnet32_read_csr (pcnet32_dev, 24) | (pcnet32_read_csr (pcnet32_dev, 25) << 16);
417 printf ("rxring: 0x%x\n", ring);
419 ring = pcnet32_read_csr (pcnet32_dev, 30) | (pcnet32_read_csr (pcnet32_dev, 31) << 16);
420 printf ("txring: 0x%x\n", ring);
422 ring = pcnet32_read_csr (pcnet32_dev, 76);
423 printf ("rlen: 0x%x\n", ring);
426 ring = pcnet32_read_csr (pcnet32_dev, 78);
427 printf ("tlen: 0x%x\n", ring);
429 timer_wait (100);
431 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, PCNET32_STATUS_START | PCNET32_STATUS_IENA);
433 //timer_wait (10000);
435 netdev_t *ifdev = netdev_create ();
437 if (!ifdev)
438 return 0;
440 memcpy (ifdev->dev_addr, dev->addr_mac, sizeof (dev->addr_mac));
442 ifdev->read = &pcnet32_read;
443 ifdev->write = &pcnet32_write;
445 // timer_wait (30000);
447 return 1;
450 unsigned pcnet32_ring_create (struct pcnet32_dev_t *dev, struct pcnet32_init_t *iblock)
452 /* create tx ring */
453 struct pcnet32_ringtx_t *ringtx = (struct pcnet32_ringtx_t *) 0x51000;
455 iblock->tdra = (unsigned) ringtx;
457 /* create rx ring */
458 struct pcnet32_ringrx_t *ringrx = (struct pcnet32_ringrx_t *) 0x59000;
460 iblock->rdra = (unsigned) ringrx;
462 unsigned short index = 0;
463 for (index = 0; index < pcnet32_ring_xlen[PCNET32_BUF_ENC_RX]; index ++) {
464 ringrx[index].rmd0.rbadr = (unsigned) kmalloc (sizeof (unsigned char) * PCNET32_RING_RX_BUF_LEN);
465 ringrx[index].rmd1.bcnt = -PCNET32_RING_RX_BUF_LEN;
466 ringrx[index].rmd1.own = ~0;
467 //ringrx[index].rmd3.res = 0;
468 ringrx[index].rmd1.ones = ~0;
471 return 1;
474 void pcnet32_int ()
476 struct pcnet32_dev_t *dev = pcnet32_dev;
478 int status = pcnet32_read_csr (dev, PCNET32_CSR_STATUS);
480 /* disable device interrupts */
481 if (status & 0x8600)
482 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, status & ~PCNET32_STATUS_IENA);
484 if (status & PCNET32_INT_ERR)
485 kprintf ("pcnet32 -> device error\n");
487 if (status & PCNET32_INT_RERR)
488 kprintf ("pcnet32 -> read error\n");
490 if (status & PCNET32_INT_WERR)
491 kprintf ("pcnet32 -> write error\n");
493 if (status & PCNET32_INT_RINT) {
494 kprintf ("pcnet32 -> pcnet32_int_rx ()\n");
495 pcnet32_int_rx (dev);
498 kprintf ("pcnet32 -> interrupt (0x%x)\n", status);
500 //outw (dev->addr_io + PCNET32_IO_RDP, 0x7940);
502 /* enable device interrupts */
503 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, PCNET32_STATUS_IENA);
506 unsigned pcnet32_int_rx (struct pcnet32_dev_t *dev)
508 struct pcnet32_ringrx_t *ringrx = (struct pcnet32_ringrx_t *) 0x59000;
510 unsigned short index = 0;
511 for (index = 0; index < pcnet32_ring_xlen[PCNET32_BUF_ENC_RX]; index ++) {
513 kprintf ("own: %d\n", ringrx[index].rmd1.own);
515 kprintf ("buf (%d): '%s'\n", ringrx[index].rmd2.mcnt, ringrx[index].rmd0.rbadr);
517 kprintf ("zeros (%d): 0x%x\n", ringrx[index].rmd2.zeros, ringrx[index].rmd2.zeros);
518 kprintf ("ones: %d / 0x%x\n", ringrx[index].rmd1.ones, ringrx[index].rmd1.ones);
519 kprintf ("err: %d / 0x%x\n", ringrx[index].rmd1.err, ringrx[index].rmd1.err);
520 kprintf ("bcnt: %d / 0x%x\n", ringrx[index].rmd1.bcnt, ringrx[index].rmd1.bcnt);
524 return 1;
527 bool pcnet32_acthandler (unsigned act, char *block, unsigned block_len)
529 switch (act) {
530 case DEV_ACT_INIT:
532 return init_pcnet32 ();
534 break;
535 case DEV_ACT_READ:
537 unsigned ring = pcnet32_read_csr (pcnet32_dev, 24) | (pcnet32_read_csr (pcnet32_dev, 25) << 16);
538 printf ("rxring: 0x%x\n", ring);
540 ring = pcnet32_read_csr (pcnet32_dev, 30) | (pcnet32_read_csr (pcnet32_dev, 31) << 16);
541 printf ("txring: 0x%x\n", ring);
543 ring = pcnet32_read_csr (pcnet32_dev, 76);
544 printf ("rlen: 0x%x\n", ring);
546 ring = pcnet32_read_csr (pcnet32_dev, 78);
547 printf ("tlen: 0x%x\n", ring);
549 ring = (pcnet32_read_csr (pcnet32_dev, 2) << 16) | pcnet32_read_csr (pcnet32_dev, 1);
550 printf ("init: 0x%x / 0x%x\n", ring, init_block);
552 return 1;
554 break;
555 case DEV_ACT_WRITE:
558 return 1;
560 break;
563 return 0;
565 #endif