1 #include <minix/drivers.h>
2 #include <minix/netdriver.h>
3 #include <machine/pci.h>
4 #include <sys/mman.h>
5 #include "vt6105.h"
6 #include "io.h"
7
8 /* global value */
9 static NDR_driver g_driver;
10 static int g_instance;
11
12 /* driver interface */
13 static int NDR_init(unsigned int instance, netdriver_addr_t * addr,
14 uint32_t * caps, unsigned int * ticks);
15 static void NDR_stop(void);
16 static void NDR_set_mode(unsigned int mode,
17 const netdriver_addr_t * mcast_list, unsigned int mcast_count);
18 static ssize_t NDR_recv(struct netdriver_data *data, size_t max);
19 static int NDR_send(struct netdriver_data *data, size_t size);
20 static void NDR_intr(unsigned int mask);
21
22 /* internal function */
23 static int dev_probe(NDR_driver *pdev, int instance);
24 static int dev_init_buf(NDR_driver *pdev);
25 static int dev_init_hw(NDR_driver *pdev, netdriver_addr_t *addr);
26 static int dev_reset_hw(NDR_driver *pdev);
27 static void dev_conf_addr(NDR_driver *pdev, netdriver_addr_t *addr);
28 static void dev_handler(NDR_driver *pdev);
29 static void dev_check_ints(NDR_driver *pdev);
30
31 /* developer interface */
32 static int dev_real_reset(u32_t *base);
33 static int dev_init_io(u32_t *base);
34 static int dev_init_mii(u32_t *base);
35 static void dev_intr_control(u32_t *base, int flag);
36 static void dev_rx_tx_control(u32_t *base, int flag);
37 static void dev_get_addr(u32_t *base, u8_t *pa);
38 static int dev_check_link(u32_t *base);
39 static void dev_set_rec_mode(u32_t *base, int mode);
40 static void dev_start_tx(u32_t *base);
41 static u32_t dev_read_clear_intr_status(u32_t *base);
42 static void dev_init_rx_desc(NDR_desc *desc_start, int index, size_t buf_size,
43 phys_bytes buf_dma, int max_desc_num, phys_bytes desc_dma_start);
44 static void dev_init_tx_desc(NDR_desc *desc_start, int index, size_t buf_size,
45 phys_bytes buf_dma, int max_desc_num, phys_bytes desc_dma_start);
46 static void dev_set_desc_reg(u32_t *base, phys_bytes rx_addr,
47 phys_bytes tx_addr);
48 static int dev_rx_ok_desc(u32_t *base, NDR_desc *desc, int index);
49 static int dev_rx_len_desc(u32_t *base, NDR_desc *desc, int index);
50 static void dev_set_rx_desc_done(u32_t *base, NDR_desc *desc, int index);
51 static void dev_set_tx_desc_prepare(u32_t *base, NDR_desc *desc, int index,
52 size_t data_size);
53 static int dev_tx_ok_desc(u32_t *base, NDR_desc *desc, int index);
54 static void dev_set_tx_desc_done(u32_t *base, NDR_desc *desc, int index);
55
56 /* ======= Developer implemented function ======= */
57 /* ====== Self-defined function ======*/
58
59 /* ====== Developer interface ======*/
60 /* Real hardware reset (### RESET_HARDWARE_CAN_FAIL ###)
61 * -- Return OK means success, Others means failure */
dev_real_reset(u32_t * base)62 static int dev_real_reset(u32_t *base) {
63 u32_t base0 = base[0];
64 ndr_out16(base0, REG_CR, CMD_RESET);
65 micro_delay(5000);
66 if (ndr_in16(base0, REG_CR) & CMD_RESET) {
67 ndr_out8(base0, REG_MCR, 0x40);
68 micro_delay(5000);
69 if (ndr_in16(base0, REG_CR) & CMD_RESET)
70 return -EIO;
71 }
72 return OK;
73 }
74
75 /* Intialize other hardware I/O registers (### INIT_HARDWARE_IO_CAN_FAIL ###)
76 * -- Return OK means success, Others means failure */
dev_init_io(u32_t * base)77 static int dev_init_io(u32_t *base) {
78 u32_t base0 = base[0];
79 u8_t stick;
80 stick = ndr_in8(base0, REG_STICK);
81 ndr_out8(base0, REG_STICK, stick & 0xfc);
82 ndr_out16(base0, REG_BCR, 0x0006);
83 ndr_out8(base0, REG_TCR, 0x20);
84 ndr_out8(base0, REG_RCR, 0x78);
85 return OK;
86 }
87
88 /* Intialize MII interface (### MII_INIT_CAN_FAIL ###)
89 -- Return OK means success, Others means failure */
dev_init_mii(u32_t * base)90 static int dev_init_mii(u32_t *base) {
91 u32_t base0 = base[0];
92 ndr_out8(base0, REG_MII_CR, 0);
93 ndr_out8(base0, REG_MII_REG, 0x01);
94 ndr_out8(base0, REG_MII_CR, 0x80);
95 micro_delay(5000);
96 if (!(ndr_in8(base0, REG_MII_REG) & 0x20)) {
97 printf("NDR: Fail to monitor linkage\n");
98 return -EIO;
99 }
100 ndr_out8(base0, REG_MII_REG, 0x41);
101 return OK;
102 }
103
104 /* Enable or disable interrupt (### INTR_ENABLE_DISABLE ###) */
dev_intr_control(u32_t * base,int flag)105 static void dev_intr_control(u32_t *base, int flag) {
106 u32_t data, base0 = base[0];
107 data = ndr_in16(base0, REG_IMR);
108 if (flag == INTR_ENABLE)
109 ndr_out16(base0, REG_IMR, data | CMD_INTR_ENABLE);
110 else if (flag == INTR_DISABLE)
111 ndr_out16(base0, REG_IMR, data & ~CMD_INTR_ENABLE);
112 }
113
114 /* Enable or disable Rx/Tx (### RX_TX_ENABLE_DISABLE ###) */
dev_rx_tx_control(u32_t * base,int flag)115 static void dev_rx_tx_control(u32_t *base, int flag) {
116 u32_t data, base0 = base[0];
117 if (flag == RX_TX_ENABLE) {
118 data = CMD_START | CMD_RX_ON | CMD_TX_ON | CMD_NO_POLL | CMD_FDUPLEX;
119 ndr_out16(base0, REG_CR, data);
120 }
121 else if (flag == RX_TX_DISABLE) {
122 ndr_out16(base0, REG_CR, CMD_STOP);
123 }
124 }
125
126 /* Get MAC address to the array 'pa' (### GET_MAC_ADDR ###) */
dev_get_addr(u32_t * base,u8_t * pa)127 static void dev_get_addr(u32_t *base, u8_t *pa) {
128 u32_t i, base0 = base[0];
129 for (i = 0; i < 6; i++)
130 pa[i] = ndr_in8(base0, REG_ADDR + i);
131 }
132
133 /* Check link status (### CHECK_LINK ###)
134 * -- Return LINK_UP or LINK_DOWN */
dev_check_link(u32_t * base)135 static int dev_check_link(u32_t *base) {
136 u32_t data, base0 = base[0];
137 ndr_out8(base0, REG_MII_PHY, 0x01);
138 ndr_out8(base0, REG_MII_REG, 0x01);
139 ndr_out8(base0, REG_MII_CR, 0x40);
140 micro_delay(5000);
141 if (ndr_in8(base0, REG_MII_CR) & 0x40)
142 printf("NDR: Fail to get linkage\n");
143 data = ndr_in16(base0, REG_MII_DATA);
144 if (data & LINK_STATUS)
145 return LINK_UP;
146 return LINK_DOWN;
147 }
148
149 /* Set driver receive mode (### SET_REC_MODE ###) */
dev_set_rec_mode(u32_t * base,int mode)150 static void dev_set_rec_mode(u32_t *base, int mode) {
151 u32_t data, base0 = base[0];
152 data = ndr_in8(base0, REG_RCR);
153 data &= ~(CMD_RCR_UNICAST | CMD_RCR_MULTICAST | CMD_RCR_BROADCAST);
154 if (mode & NDEV_MODE_PROMISC)
155 data |= CMD_RCR_UNICAST | CMD_RCR_BROADCAST | CMD_RCR_MULTICAST;
156 if (mode & NDEV_MODE_BCAST)
157 data |= CMD_RCR_BROADCAST;
158 if (mode & (NDEV_MODE_MCAST_LIST | NDEV_MODE_MCAST_ALL))
159 data |= CMD_RCR_MULTICAST;
160 data |= CMD_RCR_UNICAST;
161 ndr_out8(base0, REG_RCR, data);
162 }
163
164 /* Start Tx channel (### START_TX_CHANNEL ###) */
dev_start_tx(u32_t * base)165 static void dev_start_tx(u32_t *base) {
166 u32_t data, base0 = base[0];
167 data = ndr_in8(base0, REG_CR);
168 ndr_out8(base0, REG_CR, data | CMD_TX_DEMAND);
169 }
170
171 /* Read and clear interrupt (### READ_CLEAR_INTR_STS ###) */
dev_read_clear_intr_status(u32_t * base)172 static u32_t dev_read_clear_intr_status(u32_t *base) {
173 u32_t data, base0 = base[0];
174 data = ndr_in16(base0, REG_ISR);
175 ndr_out16(base0, REG_ISR, data & INTR_STS_CLEAR);
176 return data;
177 }
178
179 /* ---------- WITH DESCRIPTOR ---------- */
180 /* Intialize Rx descriptor (### INIT_RX_DESC ###) */
dev_init_rx_desc(NDR_desc * desc_start,int index,size_t buf_size,phys_bytes buf_dma,int max_desc_num,phys_bytes desc_dma_start)181 static void dev_init_rx_desc(NDR_desc *desc_start, int index, size_t buf_size,
182 phys_bytes buf_dma, int max_desc_num, phys_bytes desc_dma_start) {
183 NDR_desc *desc = desc_start + index;
184 desc->status = DESC_OWN | ((buf_size << 16) & DESC_RX_LENMASK);
185 desc->addr = buf_dma;
186 desc->length = buf_size;
187 if (index == max_desc_num - 1)
188 desc->next = desc_dma_start;
189 else
190 desc->next = desc_dma_start + (index + 1) * sizeof(NDR_desc);
191 }
192
193 /* Intialize Tx descriptor (### INIT_TX_DESC ###) */
dev_init_tx_desc(NDR_desc * desc_start,int index,size_t buf_size,phys_bytes buf_dma,int max_desc_num,phys_bytes desc_dma_start)194 static void dev_init_tx_desc(NDR_desc *desc_start, int index, size_t buf_size,
195 phys_bytes buf_dma, int max_desc_num, phys_bytes desc_dma_start) {
196 NDR_desc *desc = desc_start + index;
197 desc->addr = buf_dma;
198 desc->length = buf_size;
199 if (index == max_desc_num - 1)
200 desc->next = desc_dma_start;
201 else
202 desc->next = desc_dma_start + (index + 1) * sizeof(NDR_desc);
203 }
204
205 /* Set Rx/Tx descriptor address into device register (### SET_DESC_REG ###) */
dev_set_desc_reg(u32_t * base,phys_bytes rx_addr,phys_bytes tx_addr)206 static void dev_set_desc_reg(u32_t *base, phys_bytes rx_addr,
207 phys_bytes tx_addr) {
208 u32_t base0 = base[0];
209 ndr_out32(base0, REG_RX_DESC_BASE, rx_addr);
210 ndr_out32(base0, REG_TX_DESC_BASE, tx_addr);
211 }
212
213 /* Check whether Rx is OK from Rx descriptor (### CHECK_RX_OK_FROM_DESC ###)
214 * -- Current buffer number is index
215 * -- Return RX_OK or RX_SUSPEND or RX_ERROR */
dev_rx_ok_desc(u32_t * base,NDR_desc * desc,int index)216 static int dev_rx_ok_desc(u32_t *base, NDR_desc *desc, int index) {
217 if (!(desc->status & DESC_OWN)) {
218 if (desc->status & DESC_RX_ERROR)
219 return RX_ERROR;
220 if ((desc->status & DESC_RX_NORMAL) == DESC_RX_NORMAL)
221 return RX_OK;
222 }
223 return RX_SUSPEND;
224 }
225
226 /* Get length from Rx descriptor (### GET_RX_LENGTH_FROM_DESC ###)
227 * -- Current buffer number is index
228 * -- Return the length */
dev_rx_len_desc(u32_t * base,NDR_desc * desc,int index)229 static int dev_rx_len_desc(u32_t *base, NDR_desc *desc, int index) {
230 return ((desc->status & DESC_RX_LENMASK) >> 16) - NDEV_ETH_PACKET_CRC;
231 }
232
233 /* Set Rx descriptor after Rx done (### SET_RX_DESC_DONE ###)
234 * -- Current buffer number is index */
dev_set_rx_desc_done(u32_t * base,NDR_desc * desc,int index)235 static void dev_set_rx_desc_done(u32_t *base, NDR_desc *desc, int index) {
236 desc->status = DESC_OWN;
237 }
238
239 /* Set Tx descriptor to prepare transmitting (### SET_TX_DESC_PREPARE)
240 * -- Current buffer number is index */
dev_set_tx_desc_prepare(u32_t * base,NDR_desc * desc,int index,size_t data_size)241 static void dev_set_tx_desc_prepare(u32_t *base, NDR_desc *desc, int index,
242 size_t data_size) {
243 desc->status = DESC_OWN | DESC_FIRST | DESC_LAST;
244 desc->length = 0x00e08000 | (data_size > 60 ? data_size : 60);
245 }
246
247 /* Check whether Tx is OK from Tx descriptor (### CHECK_TX_OK_FROM_DESC ###)
248 * -- Current buffer number is index
249 * -- Return TX_OK or TX_SUSPEND or TX_ERROR */
dev_tx_ok_desc(u32_t * base,NDR_desc * desc,int index)250 static int dev_tx_ok_desc(u32_t *base, NDR_desc *desc, int index) {
251 if (!(desc->status & DESC_OWN)) {
252 if (desc->status & DESC_TX_ERROR)
253 return TX_ERROR;
254 return TX_OK;
255 }
256 return TX_SUSPEND;
257 }
258
259 /* Set Tx descriptor after Tx done (### SET_TX_DESC_DONE ###)
260 * -- Current buffer number is index */
dev_set_tx_desc_done(u32_t * base,NDR_desc * desc,int index)261 static void dev_set_tx_desc_done(u32_t *base, NDR_desc *desc, int index) {
262 desc->status = 0;
263 }
264
265 /* Driver interface table */
266 static const struct netdriver NDR_table = {
267 .ndr_name = "vr",
268 .ndr_init = NDR_init,
269 .ndr_stop = NDR_stop,
270 .ndr_set_mode = NDR_set_mode,
271 .ndr_recv = NDR_recv,
272 .ndr_send = NDR_send,
273 .ndr_intr = NDR_intr,
274 };
275
main(int argc,char * argv[])276 int main(int argc, char *argv[]) {
277 env_setargs(argc, argv);
278 netdriver_task(&NDR_table);
279 }
280
281 /* Initialize the driver */
282 static int
NDR_init(unsigned int instance,netdriver_addr_t * addr,uint32_t * caps,unsigned int * ticks __unused)283 NDR_init(unsigned int instance, netdriver_addr_t * addr, uint32_t * caps,
284 unsigned int * ticks __unused)
285 {
286 int i, ret = 0;
287
288 /* Intialize driver data structure */
289 memset(&g_driver, 0, sizeof(g_driver));
290 g_driver.link = LINK_UNKNOWN;
291 g_instance = instance;
292
293 /* Probe the device */
294 if (dev_probe(&g_driver, instance)) {
295 printf("NDR: Device is not found\n");
296 ret = -ENODEV;
297 goto err_probe;
298 }
299
300 /* Intialize hardware */
301 if (dev_init_hw(&g_driver, addr)) {
302 printf("NDR: Fail to initialize hardware\n");
303 ret = -EIO;
304 goto err_init_hw;
305 }
306
307 /* Allocate and initialize buffer */
308 if (dev_init_buf(&g_driver)) {
309 printf("NDR: Fail to initialize buffer\n");
310 ret = -ENODEV;
311 goto err_init_buf;
312 }
313
314 /* Enable interrupts */
315 /* ### INTR_ENABLE_DISABLE ### */
316 dev_intr_control(g_driver.base, INTR_ENABLE);
317
318 /* Start Rx and Tx */
319 /* ### RX_TX_ENABLE_DISABLE ### */
320 dev_rx_tx_control(g_driver.base, RX_TX_ENABLE);
321
322 /* Clear send and recv flag */
323 g_driver.send_flag = FALSE;
324 g_driver.recv_flag = FALSE;
325
326 *caps = NDEV_CAP_MCAST | NDEV_CAP_BCAST;
327 return OK;
328
329 err_init_buf:
330 err_init_hw:
331 err_probe:
332 return ret;
333 }
334
335 /* Stop the driver */
NDR_stop(void)336 static void NDR_stop(void) {
337 /* Free Rx and Tx buffer*/
338 free_contig(g_driver.buf, g_driver.buf_size);
339
340 /* Stop interrupt */
341 /* ### INTR_ENABLE_DISABLE ### */
342 dev_intr_control(g_driver.base, INTR_DISABLE);
343
344 /* Stop Rx and Tx */
345 /* ### RX_TX_ENABLE_DISABLE ### */
346 dev_rx_tx_control(g_driver.base, RX_TX_DISABLE);
347 }
348
349 /* Set driver mode */
350 static void
NDR_set_mode(unsigned int mode,const netdriver_addr_t * mcast_list __unused,unsigned int mcast_count __unused)351 NDR_set_mode(unsigned int mode, const netdriver_addr_t * mcast_list __unused,
352 unsigned int mcast_count __unused)
353 {
354 g_driver.mode = mode;
355 /* Set driver receive mode */
356 /* ### SET_REC_MODE ### */
357 dev_set_rec_mode(g_driver.base, mode);
358 }
359
360 /* Receive data */
NDR_recv(struct netdriver_data * data,size_t max)361 static ssize_t NDR_recv(struct netdriver_data *data, size_t max) {
362 NDR_driver *pdev = &g_driver;
363 u32_t totlen, packlen;
364 int index, ret, offset = 0;
365 NDR_desc *desc;
366
367 index = pdev->rx_head;
368 desc = pdev->rx_desc;
369 desc += index;
370 /* Check whether Rx is OK from Rx descriptor */
371 /* ### CHECK_RX_OK_FROM_DESC ### */
372 ret = dev_rx_ok_desc(pdev->base, desc, index);
373 if (ret == RX_SUSPEND)
374 return SUSPEND;
375 else if (ret == RX_ERROR)
376 printf("NDR: Rx error now\n");
377 /* Get length from Rx descriptor */
378 /* ### GET_RX_LENGTH_FROM_DESC ### */
379 totlen = dev_rx_len_desc(pdev->base, desc, index);
380
381 /* Get data length */
382 /* ### Get , int inde, int indexxRx data length ### */
383 if (totlen < 8 || totlen > 2 * NDEV_ETH_PACKET_MAX) {
384 printf("NDR: Bad data length: %d\n", totlen);
385 panic(NULL);
386 }
387
388 packlen = totlen;
389 if (packlen > max)
390 packlen = max;
391
392 /* Copy data to user */
393 netdriver_copyout(data, 0, pdev->rx[index].buf + offset, packlen);
394
395 /* Set Rx descriptor after Rx done */
396 /* ### SET_RX_DESC_DONE ### */
397 dev_set_rx_desc_done(pdev->base, desc, index);
398 if (index == RX_BUFFER_NUM - 1)
399 index = 0;
400 else
401 index++;
402 pdev->rx_head = index;
403
404 #ifdef MY_DEBUG
405 printf("NDR: Successfully receive a packet, length = %d\n", packlen);
406 #endif
407
408 return packlen;
409 }
410
411 /* Transmit data */
NDR_send(struct netdriver_data * data,size_t size)412 static int NDR_send(struct netdriver_data *data, size_t size) {
413 NDR_driver *pdev = &g_driver;
414 int tx_head, i;
415 NDR_desc *desc;
416
417 tx_head = pdev->tx_head;
418 if (pdev->tx[tx_head].busy)
419 return SUSPEND;
420
421 /* Copy data from user */
422 netdriver_copyin(data, 0, pdev->tx[tx_head].buf, size);
423
424 /* Set busy */
425 pdev->tx[tx_head].busy = TRUE;
426 pdev->tx_busy_num++;
427
428 desc = pdev->tx_desc;
429 desc += tx_head;
430 /* Set Tx descriptor to prepare transmitting */
431 /* ### SET_TX_DESC_PREPARE ### */
432 dev_set_tx_desc_prepare(pdev->base, desc, tx_head, size);
433 if (tx_head == TX_BUFFER_NUM - 1)
434 tx_head = 0;
435 else
436 tx_head++;
437 pdev->tx_head = tx_head;
438
439 /* Start Tx channel */
440 /* ### START_TX ### */
441 dev_start_tx(pdev->base);
442
443 return 0;
444 }
445
446 /* Handle interrupt */
NDR_intr(unsigned int mask)447 static void NDR_intr(unsigned int mask) {
448 int s;
449
450 /* Run interrupt handler at driver level */
451 dev_handler(&g_driver);
452
453 /* Reenable interrupts for this hook */
454 if ((s = sys_irqenable(&g_driver.hook)) != OK)
455 printf("NDR: Cannot enable OS interrupts: %d\n", s);
456
457 /* Perform tasks based on the flagged conditions */
458 dev_check_ints(&g_driver);
459 }
460
461 /* Match the device and get base address */
dev_probe(NDR_driver * pdev,int instance)462 static int dev_probe(NDR_driver *pdev, int instance) {
463 int devind, ioflag, i;
464 u16_t cr, vid, did;
465 u32_t bar, size, base;
466 u8_t irq, rev;
467 u8_t *reg;
468
469 /* Find pci device */
470 pci_init();
471 if (!pci_first_dev(&devind, &vid, &did))
472 return -EIO;
473 while (instance--) {
474 if (!pci_next_dev(&devind, &vid, &did))
475 return -EIO;
476 }
477 pci_reserve(devind);
478
479 /* Enable bus mastering and I/O space */
480 cr = pci_attr_r16(devind, PCI_CR);
481 pci_attr_w16(devind, PCI_CR, cr | 0x105);
482
483 /* Get base address */
484 for (i = 0; i < 6; i++)
485 pdev->base[i] = 0;
486 #ifdef DMA_BASE_IOMAP
487 for (i = 0; i < 6; i++) {
488 if (pci_get_bar(devind, PCI_BAR + i * 4, &base, &size, &ioflag)) {
489 /* printf("NDR: Fail to get PCI BAR\n"); */
490 continue;
491 }
492 if (ioflag) {
493 /* printf("NDR: PCI BAR is not for memory\n"); */
494 continue;
495 }
496 if ((reg = vm_map_phys(SELF, (void *)base, size)) == MAP_FAILED) {
497 printf("NDR: Fail to map hardware registers from PCI\n");
498 return -EIO;
499 }
500 pdev->base[i] = (u32_t)reg;
501 }
502 #else
503 for (i = 0; i < 6; i++)
504 pdev->base[i] = pci_attr_r32(devind, PCI_BAR + i * 4) & 0xffffffe0;
505 #endif
506 pdev->dev_name = pci_dev_name(vid, did);
507 pdev->irq = pci_attr_r8(devind, PCI_ILR);
508 pdev->revision = pci_attr_r8(devind, PCI_REV);
509 pdev->did = did;
510 pdev->vid = vid;
511 pdev->devind = devind;
512
513 #ifdef MY_DEBUG
514 printf("NDR: Hardware name is %s\n", pdev->dev_name);
515 for (i = 0; i < 6; i++)
516 printf("NDR: PCI BAR%d is 0x%08x\n", i, pdev->base[i]);
517 printf("NDR: IRQ number is 0x%02x\n", pdev->irq);
518 #endif
519
520 return 0;
521 }
522
523 /* Intialize hardware */
dev_init_hw(NDR_driver * pdev,netdriver_addr_t * addr)524 static int dev_init_hw(NDR_driver *pdev, netdriver_addr_t *addr) {
525 int r, ret;
526
527 /* Set the OS interrupt handler */
528 pdev->hook = pdev->irq;
529 if ((r = sys_irqsetpolicy(pdev->irq, 0, &pdev->hook)) != OK) {
530 printf("NDR: Fail to set OS IRQ policy: %d\n", r);
531 ret = -EFAULT;
532 goto err_irq_policy;
533 }
534
535 /* Reset hardware */
536 if (dev_reset_hw(pdev)) {
537 printf("NDR: Fail to reset the device\n");
538 ret = -EIO;
539 goto err_reset_hw;
540 }
541
542 /* Enable OS IRQ */
543 if ((r = sys_irqenable(&pdev->hook)) != OK) {
544 printf("NDR: Fail to enable OS IRQ: %d\n", r);
545 ret = -EFAULT;
546 goto err_irq_enable;
547 }
548
549 /* Configure MAC address */
550 dev_conf_addr(pdev, addr);
551
552 /* Detect link status */
553 /* ### CHECK_LINK ### */
554 pdev->link = dev_check_link(pdev->base);
555 #ifdef MY_DEBUG
556 if (pdev->link)
557 printf("NDR: Link up\n");
558 else
559 printf("NDR: Link down\n");
560 #endif
561
562 return 0;
563
564 err_reset_hw:
565 err_irq_enable:
566 err_irq_policy:
567 return ret;
568 }
569
570 /* Reset hardware */
dev_reset_hw(NDR_driver * pdev)571 static int dev_reset_hw(NDR_driver *pdev) {
572 int ret;
573
574 /* Reset the chip */
575 /* ### RESET_HARDWARE_CAN_FAIL ### */
576 if (dev_real_reset(pdev->base)) {
577 printf("NDR: Fail to reset the hardware\n");
578 ret = -EIO;
579 goto err_real_reset;
580 }
581
582 /* Initialize other hardware I/O registers */
583 /* ### SET_RX_DESC_REG ### */
584 if (dev_init_io(pdev->base)) {
585 printf("NDR: Fail to initialize I/O registers\n");
586 ret = -EIO;
587 goto err_init_io;
588 }
589
590 /* Initialize MII interface */
591 /* ### MII_INIT_CAN_FAIL ### */
592 if (dev_init_mii(pdev->base)) {
593 printf("NDR: Fail to initialize MII interface\n");
594 ret = -EIO;
595 goto err_init_mii;
596 }
597
598 return 0;
599
600 err_init_mii:
601 err_init_io:
602 err_real_reset:
603 return ret;
604 }
605
606 /* Configure MAC address */
dev_conf_addr(NDR_driver * pdev,netdriver_addr_t * addr)607 static void dev_conf_addr(NDR_driver *pdev, netdriver_addr_t *addr) {
608 u8_t pa[6];
609
610 /* Get MAC address */
611 /* ### GET_MAC_ADDR ### */
612 dev_get_addr(pdev->base, pa);
613 addr->na_addr[0] = pa[0];
614 addr->na_addr[1] = pa[1];
615 addr->na_addr[2] = pa[2];
616 addr->na_addr[3] = pa[3];
617 addr->na_addr[4] = pa[4];
618 addr->na_addr[5] = pa[5];
619 #ifdef MY_DEBUG
620 printf("NDR: Ethernet address is %02x:%02x:%02x:%02x:%02x:%02x\n",
621 addr->na_addr[0], addr->na_addr[1], addr->na_addr[2],
622 addr->na_addr[3], addr->na_addr[4], addr->na_addr[5]);
623 #endif
624 }
625
626 /* Allocate and initialize buffer */
dev_init_buf(NDR_driver * pdev)627 static int dev_init_buf(NDR_driver *pdev) {
628 size_t rx_desc_size, tx_desc_size, rx_buf_size, tx_buf_size, tot_buf_size;
629 phys_bytes buf_dma;
630 char *buf;
631 int i;
632
633 /* Build Rx and Tx buffer */
634 tx_buf_size = TX_BUF_SIZE;
635 if (tx_buf_size % 4)
636 tx_buf_size += 4 - (tx_buf_size % 4);
637 rx_buf_size = RX_BUF_SIZE;
638 if (rx_buf_size % 4)
639 rx_buf_size += 4 - (rx_buf_size % 4);
640 tot_buf_size = TX_BUFFER_NUM * tx_buf_size + RX_BUFFER_NUM * rx_buf_size;
641 rx_desc_size = RX_BUFFER_NUM * sizeof(NDR_desc);
642 tx_desc_size = TX_BUFFER_NUM * sizeof(NDR_desc);
643 tot_buf_size += rx_desc_size + tx_desc_size;
644 if (tot_buf_size % 4096)
645 tot_buf_size += 4096 - (tot_buf_size % 4096);
646
647 if (!(buf = alloc_contig(tot_buf_size, 0, &buf_dma))) {
648 printf("NDR: Fail to allocate memory\n");
649 return -ENOMEM;
650 }
651 pdev->buf_size = tot_buf_size;
652 pdev->buf = buf;
653
654 /* Rx descriptor buffer location */
655 pdev->rx_desc = (NDR_desc *)buf;
656 pdev->rx_desc_dma = buf_dma;
657 memset(buf, 0, rx_desc_size);
658 buf += rx_desc_size;
659 buf_dma += rx_desc_size;
660
661 /* Tx descriptor buffer location */
662 pdev->tx_desc = (NDR_desc *)buf;
663 pdev->tx_desc_dma = buf_dma;
664 memset(buf, 0, tx_desc_size);
665 buf += tx_desc_size;
666 buf_dma += tx_desc_size;
667
668 /* Rx buffer assignment */
669 for (i = 0; i < RX_BUFFER_NUM; i++) {
670 /* Initialize Rx buffer */
671 pdev->rx[i].buf_dma = buf_dma;
672 pdev->rx[i].buf = buf;
673 buf_dma += rx_buf_size;
674 buf += rx_buf_size;
675 /* Set Rx descriptor */
676 /* ### INIT_RX_DESC ### */
677 dev_init_rx_desc(pdev->rx_desc, i, rx_buf_size, pdev->rx[i].buf_dma,
678 RX_BUFFER_NUM, pdev->rx_desc_dma);
679 }
680
681 /* Tx buffer assignment */
682 for (i = 0; i < TX_BUFFER_NUM; i++) {
683 /* Set Tx buffer */
684 pdev->tx[i].busy = 0;
685 pdev->tx[i].buf_dma = buf_dma;
686 pdev->tx[i].buf = buf;
687 buf_dma += tx_buf_size;
688 buf += tx_buf_size;
689 /* Initialize Tx descriptor */
690 /* ### INIT_TX_DESC ### */
691 dev_init_tx_desc(pdev->tx_desc, i, tx_buf_size, pdev->tx[i].buf_dma,
692 TX_BUFFER_NUM, pdev->tx_desc_dma);
693 }
694
695 /* Set Rx/Tx descriptor address into device register */
696 /* ### SET_DESC_REG ### */
697 dev_set_desc_reg(pdev->base, g_driver.rx_desc_dma,
698 g_driver.tx_desc_dma);
699
700 pdev->tx_busy_num = 0;
701 pdev->tx_head = 0;
702 pdev->tx_tail = 0;
703 pdev->rx_head = 0;
704
705 return 0;
706 }
707
708 /* Real handler interrupt */
dev_handler(NDR_driver * pdev)709 static void dev_handler(NDR_driver *pdev) {
710 u32_t intr_status;
711 int tx_head, tx_tail, index, flag = 0, ret;
712 NDR_desc *desc;
713
714 /* Read and clear interrupt status */
715 /* ### READ_CLEAR_INTR_STS ### */
716 intr_status = dev_read_clear_intr_status(pdev->base);
717
718 /* Enable interrupt */
719 /* ### INTR_ENABLE_DISABLE ### */
720 dev_intr_control(pdev->base, INTR_ENABLE);
721
722 /* Check link status */
723 if (intr_status & INTR_STS_LINK) {
724 pdev->link = dev_check_link(pdev->base);
725 #ifdef MY_DEBUG
726 printf("NDR: Link state change\n");
727 #endif
728 flag++;
729 }
730 /* Check Rx request status */
731 if (intr_status & INTR_STS_RX) {
732 pdev->recv_flag = TRUE;
733 flag++;
734 }
735 /* Check Tx request status */
736 if (intr_status & INTR_STS_TX) {
737 pdev->send_flag = TRUE;
738 flag++;
739
740 /* Manage Tx Buffer */
741 tx_head = pdev->tx_head;
742 tx_tail = pdev->tx_tail;
743 while (tx_tail != tx_head) {
744 if (!pdev->tx[tx_tail].busy)
745 printf("NDR: Strange, buffer not busy?\n");
746 index = tx_tail;
747 desc = pdev->tx_desc;
748 desc += tx_tail;
749 /* Check whether Tx is OK from Tx descriptor */
750 /* ### CHECK_TX_OK_FROM_DESC ### */
751 ret = dev_tx_ok_desc(pdev->base, desc, index);
752 if (ret == TX_SUSPEND)
753 break;
754 else if (ret == TX_ERROR)
755 printf("NDR: Tx error now\n");
756
757 pdev->tx[tx_tail].busy = FALSE;
758 pdev->tx_busy_num--;
759
760 if (++tx_tail >= TX_BUFFER_NUM)
761 tx_tail = 0;
762
763 pdev->send_flag = TRUE;
764 pdev->recv_flag = TRUE;
765
766 /* Set Tx descriptor after Tx done */
767 /* ### SET_TX_DESC_DONE ### */
768 dev_set_tx_desc_done(pdev->base, desc, index);
769 #ifdef MY_DEBUG
770 printf("NDR: Successfully send a packet\n");
771 #endif
772 }
773 pdev->tx_tail = tx_tail;
774 }
775 #ifdef MY_DEBUG
776 if (!flag) {
777 printf("NDR: Unknown error in interrupt 0x%08x\n", intr_status);
778 return;
779 }
780 #endif
781 }
782
783 /* Check interrupt and perform */
dev_check_ints(NDR_driver * pdev)784 static void dev_check_ints(NDR_driver *pdev) {
785 if (!pdev->recv_flag)
786 return;
787 pdev->recv_flag = FALSE;
788
789 /* Handle data receive */
790 netdriver_recv();
791
792 /* Handle data transmit */
793 if (pdev->send_flag) {
794 pdev->send_flag = FALSE;
795 netdriver_send();
796 }
797 }
798