xref: /minix/minix/drivers/net/vt6105/vt6105.c (revision e4dbab1e)
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 */
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 */
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 */
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 ###) */
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 ###) */
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 ###) */
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 */
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 ###) */
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 ###) */
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 ###) */
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 ###) */
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 ###) */
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 ###) */
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 */
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 */
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 */
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 */
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 */
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 */
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 
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
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 */
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
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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