Kernel 0.5.9-r11; Lot of bug fixes, file_cache system was
[ZeXOS.git] / kernel / drivers / net / pcnet32 / pcnet32.c
blob7803f58de2f095f189a071fbf1d9ef421708e861
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 <arch/io.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 0x0004
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 #define __PACKED__ __attribute__ ((__packed__))
98 /* init block structure */
99 struct pcnet32_init_t {
100 unsigned short mode; /* copied into csr15 */
101 unsigned short res1:4; /* reserved */
102 unsigned char rlen:4; /* number of receive descriptor ring entries */
103 unsigned short res2:4; /* reserved */
104 unsigned short tlen:4; /* number of transmit descriptor ring entries */
105 unsigned char padr[6]; /* mac address */
106 unsigned short res3; /* reserved */
107 unsigned ladrf1; /* logical address filter 0..31 */
108 unsigned ladrf2; /* logical address filter 32..63 */
109 unsigned rdra; /* address of receive descriptor ring */
110 unsigned tdra; /* address of receive descriptor ring */
111 } __PACKED__ ;
114 /** Transmit Message Descriptor */
115 struct pcnet32_ringtx_t
117 struct
119 unsigned tbadr; /**< transmit buffer address */
120 } tmd0;
121 struct
123 unsigned bcnt:12; /**< buffer byte count (two's complement) */
124 unsigned ones:4; /**< must be 1111b */
125 unsigned res:7; /**< reserved */
126 unsigned bpe:1; /**< bus parity error */
127 unsigned enp:1; /**< end of packet */
128 unsigned stp:1; /**< start of packet */
129 unsigned def:1; /**< deferred */
130 unsigned one:1; /**< exactly one retry was needed to transmit a frame */
131 unsigned ltint:1; /**< suppress interrupts after successful transmission */
132 unsigned nofcs:1; /**< when set, the state of DXMTFCS is ignored and
133 transmitter FCS generation is activated. */
134 unsigned err:1; /**< error occured */
135 unsigned own:1; /**< 0=owned by guest driver, 1=owned by controller */
136 } tmd1;
137 struct
139 unsigned trc:4; /**< transmit retry count */
140 unsigned res:12; /**< reserved */
141 unsigned tdr:10; /**< ??? */
142 unsigned rtry:1; /**< retry error */
143 unsigned lcar:1; /**< loss of carrier */
144 unsigned lcol:1; /**< late collision */
145 unsigned exdef:1; /**< excessive deferral */
146 unsigned uflo:1; /**< underflow error */
147 unsigned buff:1; /**< out of buffers (ENP not found) */
148 } tmd2;
149 struct
151 unsigned res; /**< reserved for user defined space */
152 } tmd3;
153 } __PACKED__;
155 /** Receive Message Descriptor */
156 struct pcnet32_ringrx_t {
157 struct
159 unsigned rbadr; /**< receive buffer address */
160 } rmd0;
161 struct
163 unsigned bcnt:12; /**< buffer byte count (two's complement) */
164 unsigned ones:4; /**< must be 1111b */
165 unsigned res:4; /**< reserved */
166 unsigned bam:1; /**< broadcast address match */
167 unsigned lafm:1; /**< logical filter address match */
168 unsigned pam:1; /**< physcial address match */
169 unsigned bpe:1; /**< bus parity error */
170 unsigned enp:1; /**< end of packet */
171 unsigned stp:1; /**< start of packet */
172 unsigned buff:1; /**< buffer error */
173 unsigned crc:1; /**< crc error on incoming frame */
174 unsigned oflo:1; /**< overflow error (lost all or part of incoming frame) */
175 unsigned fram:1; /**< frame error */
176 unsigned err:1; /**< error occured */
177 unsigned own:1; /**< 0=owned by guest driver, 1=owned by controller */
178 } rmd1;
179 struct
181 unsigned mcnt:12; /**< message byte count */
182 unsigned zeros:4; /**< 0000b */
183 unsigned rpc:8; /**< receive frame tag */
184 unsigned rcc:8; /**< receive frame tag + reserved */
185 } rmd2;
186 struct
188 unsigned res; /**< reserved for user defined space */
189 } rmd3;
190 } __PACKED__;
192 /* pcnet32 device structure */
193 struct pcnet32_dev_t {
194 unsigned char irq;
195 pcidev_t *pcidev;
196 unsigned short addr_io;
197 mac_addr_t addr_mac;
200 struct pcnet32_dev_t *pcnet32_dev;
201 static netdev_t *ifdev;
204 /* I/O operations */
205 unsigned char pcnet32_read8 (struct pcnet32_dev_t *dev, unsigned short port)
207 return inb (dev->addr_io + port);
210 unsigned short pcnet32_read16 (struct pcnet32_dev_t *dev, unsigned short port)
212 return inw (dev->addr_io + port);
215 unsigned pcnet32_read32 (struct pcnet32_dev_t *dev, unsigned short port)
217 return inl (dev->addr_io + port);
220 void pcnet32_write32 (struct pcnet32_dev_t *dev, unsigned short port, unsigned val)
222 outl (dev->addr_io + port, val);
225 /* Register access */
226 unsigned pcnet32_read_csr (struct pcnet32_dev_t *dev, unsigned short reg)
228 pcnet32_write32 (dev, PCNET32_IO_RAP, reg);
229 return pcnet32_read32 (dev, PCNET32_IO_RDP);
232 void pcnet32_write_csr (struct pcnet32_dev_t *dev, unsigned short reg, unsigned short val)
234 pcnet32_write32 (dev, PCNET32_IO_RAP, reg);
235 pcnet32_write32 (dev, PCNET32_IO_RDP, val);
238 void pcnet32_write_bcr (struct pcnet32_dev_t *dev, unsigned short reg, unsigned short val)
240 pcnet32_write32 (dev, PCNET32_IO_RAP, reg);
241 pcnet32_write32 (dev, PCNET32_IO_BDP, val);
245 /* Prototype */
246 bool pcnet32_acthandler (unsigned act, char *block, unsigned block_len);
247 unsigned pcnet32_ring_create (struct pcnet32_dev_t *dev, struct pcnet32_init_t *iblock);
248 unsigned pcnet32_start (struct pcnet32_dev_t *dev);
249 void pcnet32_int ();
250 unsigned pcnet32_int_rx (struct pcnet32_dev_t *dev);
251 unsigned pcnet32_tx (char *buf, unsigned len);
253 /* READ/WRITE func */
254 unsigned pcnet32_read (char *buf, unsigned len)
256 return pcnet32_acthandler (DEV_ACT_READ, buf, len);
259 unsigned pcnet32_write (char *buf, unsigned len)
261 return pcnet32_acthandler (DEV_ACT_WRITE, buf, len);
264 /* detect pcnet32 device in PC */
265 pcidev_t *pcnet32_detect ()
267 /* First detect network card - is connected to PCI bus ?*/
268 pcidev_t *pcidev = pcidev_find (AMD_VENDORID, PCNET_DEVICEID);
270 if (!pcidev)
271 return 0;
273 return pcidev;
276 /* INIT sequence */
277 unsigned init_pcnet32 ()
279 unsigned i = 0;
281 pcidev_t *pcidev = pcnet32_detect ();
283 if (!pcidev)
284 return 0;
286 struct pcnet32_dev_t *dev = (struct pcnet32_dev_t *) kmalloc (sizeof (struct pcnet32_dev_t));
288 if (!dev)
289 return 0;
291 /* get irq id */
292 dev->irq = pcidev->u.h0.interrupt_line;
293 dev->addr_io = pcidev->u.h0.base_registers[0];
295 // get mac address from ethernet
296 for (i = 0; i < 6; i++)
297 dev->addr_mac[i] = pcnet32_read8 (dev, i);
299 irq_install_handler (dev->irq, pcnet32_int);
300 DPRINT ("pcnet32 irq: %d\n", dev->irq);
302 pcnet32_dev = dev;
304 return pcnet32_start (dev);
307 unsigned init_block;
308 unsigned pcnet32_start (struct pcnet32_dev_t *dev)
310 struct pcnet32_init_t *iblock = (struct pcnet32_init_t *) 0x50000; // TODO: page aligned address
312 if (!iblock)
313 return 0;
315 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, PCNET32_STATUS_STOP);
317 int ret = pcnet32_ring_create (dev, iblock);
319 //pcnet32_write_csr (dev, 58, ~0);
321 pcnet32_read32 (dev, PCNET32_IO_RESET);
322 pcnet32_write32 (dev, PCNET32_IO_RESET, 0);
324 iblock->mode = 0x0; // 0x8000 promiskuitni rezim
326 iblock->rlen = PCNET32_BUF_ENC_RX;
328 iblock->tlen = PCNET32_BUF_ENC_TX;
330 memcpy (iblock->padr, dev->addr_mac, 6);
332 iblock->ladrf1 = (unsigned) ~0;
333 iblock->ladrf2 = (unsigned) ~0;
335 DPRINT ("init block: %d\n", sizeof (struct pcnet32_init_t));
336 DPRINT ("rxring: 0x%x / txring: 0x%x\n", iblock->rdra, iblock->tdra);
338 /* set to 32bit mode */
339 pcnet32_write32 (dev, PCNET32_IO_RDP, 0);
340 pcnet32_write_bcr (dev, 20, 0x0002);
342 init_block = (unsigned) iblock;
344 pcnet32_write_csr (dev, 1, init_block);
345 pcnet32_write_csr (dev, 2, ((unsigned) init_block >> 16));
347 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, PCNET32_STATUS_INIT);
349 while (!(pcnet32_read_csr (dev, PCNET32_CSR_STATUS) & PCNET32_STATUS_IDON));
351 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, PCNET32_STATUS_START | PCNET32_STATUS_IENA);
353 ifdev = netdev_create (dev->addr_mac, &pcnet32_read, &pcnet32_write);
355 if (!ifdev)
356 return 0;
358 return 1;
361 unsigned pcnet32_ring_create (struct pcnet32_dev_t *dev, struct pcnet32_init_t *iblock)
363 /* create tx ring */
364 struct pcnet32_ringtx_t *ringtx = (struct pcnet32_ringtx_t *) 0x51000;
366 iblock->tdra = (unsigned) ringtx;
368 /* create rx ring */
369 struct pcnet32_ringrx_t *ringrx = (struct pcnet32_ringrx_t *) 0x59000;
371 iblock->rdra = (unsigned) ringrx;
373 unsigned short index = 0;
374 for (index = 0; index < pcnet32_ring_xlen[PCNET32_BUF_ENC_RX]; index ++) {
375 ringrx[index].rmd0.rbadr = (unsigned) kmalloc (sizeof (unsigned char) * PCNET32_RING_RX_BUF_LEN);
376 ringrx[index].rmd1.bcnt = 2048;
377 ringrx[index].rmd1.own = ~0;
378 ringrx[index].rmd3.res = 0;
379 ringrx[index].rmd1.ones = ~0;
382 return 1;
385 unsigned kix = 0;
386 void pcnet32_int ()
388 struct pcnet32_dev_t *dev = pcnet32_dev;
390 int status = pcnet32_read_csr (dev, PCNET32_CSR_STATUS);
392 /* disable device interrupts */
393 if (status & 0x8600)
394 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, status & ~PCNET32_STATUS_IENA);
396 if (status & PCNET32_INT_ERR) {
397 kprintf ("pcnet32 -> device error\n");
398 if (kix > 5) {
399 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, PCNET32_STATUS_STOP);
400 kix = 0;
402 kix ++;
405 if (status & PCNET32_INT_RERR)
406 kprintf ("pcnet32 -> read error\n");
408 if (status & PCNET32_INT_WERR)
409 kprintf ("pcnet32 -> write error\n");
411 if (status & PCNET32_INT_RINT) {
412 //kprintf ("pcnet32 -> pcnet32_int_rx ()\n");
413 pcnet32_int_rx (dev);
416 //kprintf ("pcnet32 -> interrupt (0x%x)\n", status);
418 /* enable device interrupts */
419 pcnet32_write_csr (dev, PCNET32_CSR_STATUS, PCNET32_STATUS_IENA);
422 unsigned pcnet32_int_rx (struct pcnet32_dev_t *dev)
424 struct pcnet32_ringrx_t *ringrx = (struct pcnet32_ringrx_t *) 0x59000;
426 unsigned short index = 0;
427 for (index = 0; index < pcnet32_ring_xlen[PCNET32_BUF_ENC_RX]; index ++) {
429 if (ringrx[index].rmd1.own)
430 continue;
432 /* this is needed for again use, because pcnet32 change it to ~1 */
433 ringrx[index].rmd1.own = ~0;
435 char *buf = (char *) ringrx[index].rmd0.rbadr;
438 //kprintf ("zeros (%d): 0x%x\n", ringrx[index].rmd2.zeros, ringrx[index].rmd2.zeros);
439 //kprintf ("ones: %d / 0x%x\n", ringrx[index].rmd1.ones, ringrx[index].rmd1.ones);
440 //kprintf ("err: %d / 0x%x\n", ringrx[index].rmd1.err, ringrx[index].rmd1.err);
441 //kprintf ("oflo: %d / 0x%x\n", ringrx[index].rmd1.oflo, ringrx[index].rmd1.oflo);
442 //kprintf ("buff: %d / 0x%x\n", ringrx[index].rmd1.buff, ringrx[index].rmd1.buff);
443 //kprintf ("bcnt: %d / 0x%x\n", ringrx[index].rmd1.bcnt, ringrx[index].rmd1.bcnt);
445 netdev_rx_add_queue (ifdev, buf, ringrx[index].rmd2.mcnt);
448 return 1;
451 unsigned pcnet32_tx (char *buf, unsigned len)
453 /* create tx ring */
454 struct pcnet32_ringtx_t *ringtx = (struct pcnet32_ringtx_t *) 0x51000;
456 unsigned short index = 0;
457 for (index = 0; index < pcnet32_ring_xlen[PCNET32_BUF_ENC_TX]; index ++) {
458 if (ringtx[index].tmd1.own == ~0)
459 DPRINT ("pcnet32 -> bad txring.own bit!\n");
461 ringtx[index].tmd0.tbadr = (unsigned) buf;
462 ringtx[index].tmd1.bcnt = -len;
463 ringtx[index].tmd1.own = ~0;
464 ringtx[index].tmd3.res = 0;
465 ringtx[index].tmd1.ones = ~0;
466 ringtx[index].tmd1.stp = ~0;
467 ringtx[index].tmd1.enp = ~0;
471 bool pcnet32_acthandler (unsigned act, char *block, unsigned block_len)
473 switch (act) {
474 case DEV_ACT_INIT:
476 return init_pcnet32 ();
478 break;
479 case DEV_ACT_READ:
481 /* see pcnet32_int_rx interrupt */
483 return 1;
485 break;
486 case DEV_ACT_WRITE:
488 pcnet32_tx (block, block_len);
490 return 1;
492 break;
495 return 0;
497 #endif