remove const from TPL_OpenTPLFromMemory since the memory is altered
[libogc.git] / libdb / uIP / bba.c
blobf9739d9395be5c95d37bb6c8ad8cf297a4cdf781
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include "asm.h"
5 #include "processor.h"
6 #include "exi.h"
7 #include "cache.h"
8 #include "bba.h"
9 #include "uip_pbuf.h"
10 #include "uip_netif.h"
11 #include "uip_arp.h"
13 #define IFNAME0 'e'
14 #define IFNAME1 't'
16 #define BBA_MINPKTSIZE 60
18 #define BBA_CID 0x04020200
20 #define BBA_CMD_IRMASKALL 0x00
21 #define BBA_CMD_IRMASKNONE 0xF8
23 #define BBA_NCRA 0x00 /* Network Control Register A, RW */
24 #define BBA_NCRA_RESET (1<<0) /* RESET */
25 #define BBA_NCRA_ST0 (1<<1) /* ST0, Start transmit command/status */
26 #define BBA_NCRA_ST1 (1<<2) /* ST1, " */
27 #define BBA_NCRA_SR (1<<3) /* SR, Start Receive */
29 #define BBA_NCRB 0x01 /* Network Control Register B, RW */
30 #define BBA_NCRB_PR (1<<0) /* PR, Promiscuous Mode */
31 #define BBA_NCRB_CA (1<<1) /* CA, Capture Effect Mode */
32 #define BBA_NCRB_PM (1<<2) /* PM, Pass Multicast */
33 #define BBA_NCRB_PB (1<<3) /* PB, Pass Bad Frame */
34 #define BBA_NCRB_AB (1<<4) /* AB, Accept Broadcast */
35 #define BBA_NCRB_HBD (1<<5) /* HBD, reserved */
36 #define BBA_NCRB_RXINTC0 (1<<6) /* RXINTC, Receive Interrupt Counter */
37 #define BBA_NCRB_RXINTC1 (1<<7) /* " */
38 #define BBA_NCRB_1_PACKET_PER_INT (0<<6) /* 0 0 */
39 #define BBA_NCRB_2_PACKETS_PER_INT (1<<6) /* 0 1 */
40 #define BBA_NCRB_4_PACKETS_PER_INT (2<<6) /* 1 0 */
41 #define BBA_NCRB_8_PACKETS_PER_INT (3<<6) /* 1 1 */
43 #define BBA_LTPS 0x04 /* Last Transmitted Packet Status, RO */
44 #define BBA_LRPS 0x05 /* Last Received Packet Status, RO */
46 #define BBA_IMR 0x08 /* Interrupt Mask Register, RW, 00h */
47 #define BBA_IMR_FRAGIM (1<<0) /* FRAGIM, Fragment Counter Int Mask */
48 #define BBA_IMR_RIM (1<<1) /* RIM, Receive Interrupt Mask */
49 #define BBA_IMR_TIM (1<<2) /* TIM, Transmit Interrupt Mask */
50 #define BBA_IMR_REIM (1<<3) /* REIM, Receive Error Interrupt Mask */
51 #define BBA_IMR_TEIM (1<<4) /* TEIM, Transmit Error Interrupt Mask */
52 #define BBA_IMR_FIFOEIM (1<<5) /* FIFOEIM, FIFO Error Interrupt Mask */
53 #define BBA_IMR_BUSEIM (1<<6) /* BUSEIM, BUS Error Interrupt Mask */
54 #define BBA_IMR_RBFIM (1<<7) /* RBFIM, RX Buffer Full Interrupt Mask */
56 #define BBA_IR 0x09 /* Interrupt Register, RW, 00h */
57 #define BBA_IR_FRAGI (1<<0) /* FRAGI, Fragment Counter Interrupt */
58 #define BBA_IR_RI (1<<1) /* RI, Receive Interrupt */
59 #define BBA_IR_TI (1<<2) /* TI, Transmit Interrupt */
60 #define BBA_IR_REI (1<<3) /* REI, Receive Error Interrupt */
61 #define BBA_IR_TEI (1<<4) /* TEI, Transmit Error Interrupt */
62 #define BBA_IR_FIFOEI (1<<5) /* FIFOEI, FIFO Error Interrupt */
63 #define BBA_IR_BUSEI (1<<6) /* BUSEI, BUS Error Interrupt */
64 #define BBA_IR_RBFI (1<<7) /* RBFI, RX Buffer Full Interrupt */
66 #define BBA_BP 0x0a/*+0x0b*/ /* Boundary Page Pointer Register */
67 #define BBA_TLBP 0x0c/*+0x0d*/ /* TX Low Boundary Page Pointer Register */
68 #define BBA_TWP 0x0e/*+0x0f*/ /* Transmit Buffer Write Page Pointer Register */
69 #define BBA_TRP 0x12/*+0x13*/ /* Transmit Buffer Read Page Pointer Register */
70 #define BBA_RWP 0x16/*+0x17*/ /* Receive Buffer Write Page Pointer Register */
71 #define BBA_RRP 0x18/*+0x19*/ /* Receive Buffer Read Page Pointer Register */
72 #define BBA_RHBP 0x1a/*+0x1b*/ /* Receive High Boundary Page Pointer Register */
74 #define BBA_RXINTT 0x14/*+0x15*/ /* Receive Interrupt Timer Register */
76 #define BBA_NAFR_PAR0 0x20 /* Physical Address Register Byte 0 */
77 #define BBA_NAFR_PAR1 0x21 /* Physical Address Register Byte 1 */
78 #define BBA_NAFR_PAR2 0x22 /* Physical Address Register Byte 2 */
79 #define BBA_NAFR_PAR3 0x23 /* Physical Address Register Byte 3 */
80 #define BBA_NAFR_PAR4 0x24 /* Physical Address Register Byte 4 */
81 #define BBA_NAFR_PAR5 0x25 /* Physical Address Register Byte 5 */
83 #define BBA_NWAYC 0x30 /* NWAY Configuration Register, RW, 84h */
84 #define BBA_NWAYC_FD (1<<0) /* FD, Full Duplex Mode */
85 #define BBA_NWAYC_PS100 (1<<1) /* PS100/10, Port Select 100/10 */
86 #define BBA_NWAYC_ANE (1<<2) /* ANE, Autonegotiation Enable */
87 #define BBA_NWAYC_ANS_RA (1<<3) /* ANS, Restart Autonegotiation */
88 #define BBA_NWAYC_LTE (1<<7) /* LTE, Link Test Enable */
90 #define BBA_NWAYS 0x31
91 #define BBA_NWAYS_LS10 (1<<0)
92 #define BBA_NWAYS_LS100 (1<<1)
93 #define BBA_NWAYS_LPNWAY (1<<2)
94 #define BBA_NWAYS_ANCLPT (1<<3)
95 #define BBA_NWAYS_100TXF (1<<4)
96 #define BBA_NWAYS_100TXH (1<<5)
97 #define BBA_NWAYS_10TXF (1<<6)
98 #define BBA_NWAYS_10TXH (1<<7)
100 #define BBA_GCA 0x32 /* GMAC Configuration A Register, RW, 00h */
101 #define BBA_GCA_ARXERRB (1<<3) /* ARXERRB, Accept RX packet with error */
103 #define BBA_MISC 0x3d /* MISC Control Register 1, RW, 3ch */
104 #define BBA_MISC_BURSTDMA (1<<0)
105 #define BBA_MISC_DISLDMA (1<<1)
107 #define BBA_TXFIFOCNT 0x3e/*0x3f*/ /* Transmit FIFO Counter Register */
108 #define BBA_WRTXFIFOD 0x48/*-0x4b*/ /* Write TX FIFO Data Port Register */
110 #define BBA_MISC2 0x50 /* MISC Control Register 2, RW, 00h */
111 #define BBA_MISC2_HBRLEN0 (1<<0) /* HBRLEN, Host Burst Read Length */
112 #define BBA_MISC2_HBRLEN1 (1<<1) /* " */
113 #define BBA_MISC2_RUNTSIZE (1<<2) /* " */
114 #define BBA_MISC2_DREQBCTRL (1<<3) /* " */
115 #define BBA_MISC2_RINTSEL (1<<4) /* " */
116 #define BBA_MISC2_ITPSEL (3<<5) /* " */
117 #define BBA_MISC2_AUTORCVR (1<<7) /* Auto RX Full Recovery */
119 #define BBA_RX_STATUS_BF (1<<0)
120 #define BBA_RX_STATUS_CRC (1<<1)
121 #define BBA_RX_STATUS_FAE (1<<2)
122 #define BBA_RX_STATUS_FO (1<<3)
123 #define BBA_RX_STATUS_RW (1<<4)
124 #define BBA_RX_STATUS_MF (1<<5)
125 #define BBA_RX_STATUS_RF (1<<6)
126 #define BBA_RX_STATUS_RERR (1<<7)
128 #define BBA_TX_STATUS_CC0 (1<<0)
129 #define BBA_TX_STATUS_CC1 (1<<1)
130 #define BBA_TX_STATUS_CC2 (1<<2)
131 #define BBA_TX_STATUS_CC3 (1<<3)
132 #define BBA_TX_STATUS_CCMASK (0x0f)
133 #define BBA_TX_STATUS_CRSLOST (1<<4)
134 #define BBA_TX_STATUS_UF (1<<5)
135 #define BBA_TX_STATUS_OWC (1<<6)
136 #define BBA_TX_STATUS_OWN (1<<7)
137 #define BBA_TX_STATUS_TERR (1<<7)
139 #define BBA_TX_MAX_PACKET_SIZE 1518 /* 14+1500+4 */
140 #define BBA_RX_MAX_PACKET_SIZE 1536 /* 6 pages * 256 bytes */
142 #define BBA_INIT_TLBP 0x00
143 #define BBA_INIT_BP 0x01
144 #define BBA_INIT_RHBP 0x0f
145 #define BBA_INIT_RWP BBA_INIT_BP
146 #define BBA_INIT_RRP BBA_INIT_BP
148 #define BBA_NAPI_WEIGHT 16
150 #define RX_BUFFERS 16
152 #define cpu_to_be16(x) (x)
153 #define cpu_to_be32(x) (x)
154 static inline u16 cpu_to_le16(u16 x) { return (x<<8) | (x>>8);}
155 static inline u32 cpu_to_le32(u32 x) { return((x>>24) | ((x>>8)&0xff00) | ((x<<8)&0xff0000) | (x<<24));}
157 #define cpu_to_le16p(addr) (cpu_to_le16(*(addr)))
158 #define cpu_to_le32p(addr) (cpu_to_le32(*(addr)))
159 #define cpu_to_be16p(addr) (cpu_to_be16(*(addr)))
160 #define cpu_to_be32p(addr) (cpu_to_be32(*(addr)))
162 static inline void cpu_to_le16s(u16 *a) {*a = cpu_to_le16(*a);}
163 static inline void cpu_to_le32s(u32 *a) {*a = cpu_to_le32(*a);}
164 static inline void cpu_to_be16s(u16 *a) {*a = cpu_to_be16(*a);}
165 static inline void cpu_to_be32s(u32 *a) {*a = cpu_to_be32(*a);}
167 #define le16_to_cpup(x) cpu_to_le16p(x)
168 #define le32_to_cpup(x) cpu_to_le32p(x)
169 #define be16_to_cpup(x) cpu_to_be16p(x)
170 #define be32_to_cpup(x) cpu_to_be32p(x)
172 #define le16_to_cpus(x) cpu_to_le16s(x)
173 #define le32_to_cpus(x) cpu_to_le32s(x)
174 #define be16_to_cpus(x) cpu_to_be16s(x)
175 #define be32_to_cpus(x) cpu_to_be32s(x)
177 struct bba_priv {
178 u8 revid;
179 u16 devid;
180 u8 acstart;
181 s8_t state;
182 struct uip_eth_addr *ethaddr;
185 #define X(a,b) b,a
186 struct bba_descr {
187 u32 X(X(next_packet_ptr:12, packet_len:12), status:8);
188 } __attribute((packed));
190 #define _SHIFTL(v, s, w) \
191 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
192 #define _SHIFTR(v, s, w) \
193 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
195 /* new functions */
196 #define bba_select() EXI_Select(EXI_CHANNEL_0,EXI_DEVICE_2,EXI_SPEED32MHZ)
197 #define bba_deselect() EXI_Deselect(EXI_CHANNEL_0)
199 #define bba_in12(reg) ((bba_in8(reg)&0xff)|((bba_in8((reg)+1)&0x0f)<<8))
200 #define bba_out12(reg,val) do { \
201 bba_out8((reg),(val)&0xff); \
202 bba_out8((reg)+1,((val)&0x0f00)>>8); \
203 } while(0)
205 #if UIP_LOGGING == 1
206 #include <stdio.h>
207 #define UIP_LOG(m) uip_log(__FILE__,__LINE__,m)
208 #else
209 #define UIP_LOG(m)
210 #endif /* UIP_LOGGING == 1 */
212 #if UIP_STATISTICS == 1
213 struct uip_stats uip_stat;
214 #define UIP_STAT(s) s
215 #else
216 #define UIP_STAT(s)
217 #endif /* UIP_STATISTICS == 1 */
219 static s64 bba_arp_tmr = 0;
221 static struct uip_pbuf *bba_recv_pbufs = NULL;
222 static struct uip_netif *bba_netif = NULL;
223 static struct bba_priv bba_device;
224 static struct bba_descr cur_descr;
226 static void bba_cmd_ins(u32 reg,void *val,u32 len);
227 static void bba_cmd_outs(u32 reg,void *val,u32 len);
228 static void bba_ins(u32 reg,void *val,u32 len);
229 static void bba_outs(u32 reg,void *val,u32 len);
231 static void bba_devpoll(u16 *pstatus);
233 extern void udelay(int us);
234 extern u32 diff_msec(long long start,long long end);
235 extern u32 diff_usec(long long start,long long end);
236 extern long long gettime();
238 static __inline__ void bba_cmd_insnosel(u32 reg,void *val,u32 len)
240 u16 req;
241 req = reg<<8;
242 EXI_Imm(EXI_CHANNEL_0,&req,sizeof(req),EXI_WRITE,NULL);
243 EXI_Sync(EXI_CHANNEL_0);
244 EXI_ImmEx(EXI_CHANNEL_0,val,len,EXI_READ);
247 static void bba_cmd_ins(u32 reg,void *val,u32 len)
249 bba_select();
250 bba_cmd_insnosel(reg,val,len);
251 bba_deselect();
254 static __inline__ void bba_cmd_outsnosel(u32 reg,void *val,u32 len)
256 u16 req;
257 req = (reg<<8)|0x4000;
258 EXI_Imm(EXI_CHANNEL_0,&req,sizeof(req),EXI_WRITE,NULL);
259 EXI_Sync(EXI_CHANNEL_0);
260 EXI_ImmEx(EXI_CHANNEL_0,val,len,EXI_WRITE);
263 static void bba_cmd_outs(u32 reg,void *val,u32 len)
265 bba_select();
266 bba_cmd_outsnosel(reg,val,len);
267 bba_deselect();
270 static inline u8 bba_cmd_in8(u32 reg)
272 u8 val;
273 bba_cmd_ins(reg,&val,sizeof(val));
274 return val;
277 static inline u8 bba_cmd_in8_slow(u32 reg)
279 u8 val;
280 bba_select();
281 bba_cmd_insnosel(reg,&val,sizeof(val));
282 udelay(200); //usleep doesn't work on this amount, decrementer is based on 10ms, wait is 200us
283 bba_deselect();
284 return val;
287 static inline void bba_cmd_out8(u32 reg,u8 val)
289 bba_cmd_outs(reg,&val,sizeof(val));
292 static inline u8 bba_in8(u32 reg)
294 u8 val;
295 bba_ins(reg,&val,sizeof(val));
296 return val;
299 static inline void bba_out8(u32 reg,u8 val)
301 bba_outs(reg,&val,sizeof(val));
304 static inline void bba_insnosel(u32 reg,void *val,u32 len)
306 u32 req;
307 req = (reg<<8)|0x80000000;
308 EXI_Imm(EXI_CHANNEL_0,&req,sizeof(req),EXI_WRITE,NULL);
309 EXI_Sync(EXI_CHANNEL_0);
310 EXI_ImmEx(EXI_CHANNEL_0,val,len,EXI_READ);
313 static void bba_ins(u32 reg,void *val,u32 len)
315 bba_select();
316 bba_insnosel(reg,val,len);
317 bba_deselect();
320 static inline void bba_outsnoselect(u32 reg,void *val,u32 len)
322 u32 req;
323 req = (reg<<8)|0xC0000000;
324 EXI_Imm(EXI_CHANNEL_0,&req,sizeof(req),EXI_WRITE,NULL);
325 EXI_Sync(EXI_CHANNEL_0);
326 EXI_ImmEx(EXI_CHANNEL_0,val,len,EXI_WRITE);
329 static void bba_outs(u32 reg,void *val,u32 len)
331 bba_select();
332 bba_outsnoselect(reg,val,len);
333 bba_deselect();
336 static inline void bba_insregister(u32 reg)
338 u32 req;
339 req = (reg<<8)|0x80000000;
340 EXI_Imm(EXI_CHANNEL_0,&req,sizeof(req),EXI_WRITE,NULL);
341 EXI_Sync(EXI_CHANNEL_0);
344 static inline void bba_insdata(void *val,u32 len)
346 EXI_ImmEx(EXI_CHANNEL_0,val,len,EXI_READ);
350 static inline void bba_outsregister(u32 reg)
352 u32 req;
353 req = (reg<<8)|0xC0000000;
354 EXI_Imm(EXI_CHANNEL_0,&req,sizeof(req),EXI_WRITE,NULL);
355 EXI_Sync(EXI_CHANNEL_0);
358 static inline void bba_outsdata(void *val,u32 len)
360 EXI_ImmEx(EXI_CHANNEL_0,val,len,EXI_WRITE);
363 static __inline__ u32 __linkstate()
365 u8 nways = 0;
367 nways = bba_in8(BBA_NWAYS);
368 if(nways&BBA_NWAYS_LS10 || nways&BBA_NWAYS_LS100) return 1;
369 return 0;
372 static u32 __bba_getlink_state_async()
374 u32 ret;
377 if(EXI_Lock(EXI_CHANNEL_0,EXI_DEVICE_2,NULL)==0) return 0;
378 ret = __linkstate();
379 EXI_Unlock(EXI_CHANNEL_0);
380 return ret;
384 static u32 __bba_read_cid()
386 u16 cmd = 0;
387 u32 cid = 0;
389 bba_select();
390 EXI_Imm(EXI_CHANNEL_0,&cmd,2,EXI_WRITE,NULL);
391 EXI_Sync(EXI_CHANNEL_0);
392 EXI_Imm(EXI_CHANNEL_0,&cid,4,EXI_READ,NULL);
393 EXI_Sync(EXI_CHANNEL_0);
394 bba_deselect();
396 return cid;
398 static void __bba_reset()
400 bba_out8(0x60,0x00);
401 udelay(10000);
402 bba_cmd_in8_slow(0x0F);
403 udelay(10000);
404 bba_out8(BBA_NCRA,BBA_NCRA_RESET);
405 bba_out8(BBA_NCRA,0x00);
408 static void __bba_recv_init()
410 bba_out8(BBA_NCRB,(BBA_NCRB_CA|BBA_NCRB_AB));
411 bba_out8(BBA_MISC2,(BBA_MISC2_AUTORCVR));
413 bba_out12(BBA_TLBP, BBA_INIT_TLBP);
414 bba_out12(BBA_BP,BBA_INIT_BP);
415 bba_out12(BBA_RWP,BBA_INIT_RWP);
416 bba_out12(BBA_RRP,BBA_INIT_RRP);
417 bba_out12(BBA_RHBP,BBA_INIT_RHBP);
419 bba_out8(BBA_GCA,BBA_GCA_ARXERRB);
420 bba_out8(BBA_NCRA,BBA_NCRA_SR);
423 static void bba_process(struct uip_pbuf *p,struct uip_netif *dev)
425 struct uip_eth_hdr *ethhdr = NULL;
426 struct bba_priv *priv = (struct bba_priv*)dev->state;
427 const s32 ethhlen = sizeof(struct uip_eth_hdr);
429 if(p) {
430 ethhdr = p->payload;
431 switch(htons(ethhdr->type)) {
432 case UIP_ETHTYPE_IP:
433 uip_arp_ipin(dev,p);
434 uip_pbuf_header(p,-(ethhlen));
435 dev->input(p,dev);
436 break;
437 case UIP_ETHTYPE_ARP:
438 uip_arp_arpin(dev,priv->ethaddr,p);
439 break;
440 default:
441 uip_pbuf_free(p);
442 break;
447 static s8_t bba_start_rx(struct uip_netif *dev,u32 budget)
449 s32 size;
450 u16 top,pos,rwp,rrp;
451 u32 pkt_status,recvd;
452 struct uip_pbuf *p,*q;
454 UIP_LOG("bba_start_rx()\n");
456 recvd = 0;
457 rwp = bba_in12(BBA_RWP);
458 rrp = bba_in12(BBA_RRP);
459 while(recvd<budget && rrp!=rwp) {
460 bba_ins(rrp<<8,(void*)(&cur_descr),sizeof(struct bba_descr));
461 le32_to_cpus((u32*)((void*)(&cur_descr)));
463 size = cur_descr.packet_len - 4;
464 pkt_status = cur_descr.status;
465 if(size>(BBA_RX_MAX_PACKET_SIZE+4)) {
466 UIP_LOG("bba_start_rx: packet dropped due to big buffer.\n");
467 continue;
470 if(pkt_status&(BBA_RX_STATUS_RERR|BBA_RX_STATUS_FAE)) {
471 UIP_LOG("bba_start_rx: packet dropped due to receive errors.\n");
472 rwp = bba_in12(BBA_RWP);
473 rrp = bba_in12(BBA_RRP);
474 continue;
477 pos = (rrp<<8)+4;
478 top = (BBA_INIT_RHBP+1)<<8;
480 p = uip_pbuf_alloc(UIP_PBUF_RAW,size,UIP_PBUF_POOL);
481 if(p) {
482 for(q=p;q!=NULL;q=q->next) {
483 bba_select();
484 bba_insregister(pos);
485 if((pos+size)<top) {
486 bba_insdata(q->payload,size);
487 } else {
488 s32 chunk = top-pos;
490 size -= chunk;
491 pos = BBA_INIT_RRP<<8;
492 bba_insdata(q->payload,chunk);
493 bba_deselect();
495 bba_select();
496 bba_insregister(pos);
497 bba_insdata(q->payload+chunk,size);
499 bba_deselect();
500 pos += size;
503 EXI_Unlock(EXI_CHANNEL_0);
504 bba_process(p,dev);
505 EXI_Lock(EXI_CHANNEL_0,EXI_DEVICE_2,NULL);
506 } else
507 break;
509 recvd++;
511 bba_out12(BBA_RRP,(rrp=cur_descr.next_packet_ptr));
512 rwp = bba_in12(BBA_RWP);
514 return UIP_ERR_OK;
517 static inline void bba_interrupt(u16 *pstatus)
519 u8 ir,imr,status;
521 ir = bba_in8(BBA_IR);
522 imr = bba_in8(BBA_IMR);
523 status = ir&imr;
525 if(status&BBA_IR_FRAGI) {
526 bba_out8(BBA_IR,BBA_IR_FRAGI);
528 if(status&BBA_IR_RI) {
529 bba_start_rx(bba_netif,0x10);
530 bba_out8(BBA_IR,BBA_IR_RI);
532 if(status&BBA_IR_REI) {
533 bba_out8(BBA_IR,BBA_IR_REI);
535 if(status&BBA_IR_TI) {
536 bba_out8(BBA_IR,BBA_IR_TI);
538 if(status&BBA_IR_TEI) {
539 bba_out8(BBA_IR,BBA_IR_TEI);
541 if(status&BBA_IR_FIFOEI) {
542 bba_out8(BBA_IR,BBA_IR_FIFOEI);
544 if(status&BBA_IR_BUSEI) {
545 bba_out8(BBA_IR,BBA_IR_BUSEI);
547 if(status&BBA_IR_RBFI) {
548 bba_start_rx(bba_netif,0x10);
549 bba_out8(BBA_IR,BBA_IR_RBFI);
551 *pstatus |= status;
554 static s8_t bba_dochallengeresponse()
556 u16 status;
557 s32 cnt;
559 UIP_LOG("bba_dochallengeresponse()\n");
560 /* as we do not have interrupts we've to poll the irqs */
561 cnt = 0;
562 do {
563 cnt++;
564 bba_devpoll(&status);
565 if(status==0x1000) cnt = 0;
566 } while(cnt<100 && !(status&0x0800));
568 if(cnt>=1000) return UIP_ERR_IF;
569 return UIP_ERR_OK;
572 static s8_t __bba_init(struct uip_netif *dev)
574 struct bba_priv *priv = (struct bba_priv*)dev->state;
575 if(!priv) return UIP_ERR_IF;
577 __bba_reset();
579 priv->revid = bba_cmd_in8(0x01);
581 bba_cmd_outs(0x04,&priv->devid,2);
582 bba_cmd_out8(0x05,priv->acstart);
584 bba_out8(0x5b, (bba_in8(0x5b)&~0x80));
585 bba_out8(0x5e, 0x01);
586 bba_out8(0x5c, (bba_in8(0x5c)|0x04));
588 __bba_recv_init();
590 bba_ins(BBA_NAFR_PAR0,priv->ethaddr->addr, 6);
592 bba_out8(BBA_IR,0xFF);
593 bba_out8(BBA_IMR,0xFF&~BBA_IMR_FIFOEIM);
595 bba_cmd_out8(0x02,BBA_CMD_IRMASKNONE);
597 return UIP_ERR_OK;
600 static s8_t bba_init_one(struct uip_netif *dev)
602 s32 ret;
603 struct bba_priv *priv = (struct bba_priv*)dev->state;
605 if(!priv) return UIP_ERR_IF;
607 priv->revid = 0x00;
608 priv->devid = 0xD107;
609 priv->acstart = 0x4E;
611 ret = __bba_init(dev);
613 return ret;
616 static s8_t bba_probe(struct uip_netif *dev)
618 s32 ret;
619 u32 cid;
621 if(EXI_Lock(EXI_CHANNEL_0,EXI_DEVICE_2,NULL)==0) return -1;
623 cid = __bba_read_cid();
624 if(cid!=BBA_CID) {
625 EXI_Unlock(EXI_CHANNEL_0);
626 return -1;
629 ret = bba_init_one(dev);
631 EXI_Unlock(EXI_CHANNEL_0);
632 return ret;
635 static u32 bba_calc_response(struct uip_netif *dev,u32 val)
637 u8 revid_0, revid_eth_0, revid_eth_1;
638 struct bba_priv *priv = (struct bba_priv*)dev->state;
640 UIP_LOG("bba_calc_response()\n");
642 revid_0 = priv->revid;
643 revid_eth_0 = _SHIFTR(priv->devid,8,8);
644 revid_eth_1 = priv->devid&0xff;
646 u8 i0, i1, i2, i3;
647 i0 = (val & 0xff000000) >> 24;
648 i1 = (val & 0x00ff0000) >> 16;
649 i2 = (val & 0x0000ff00) >> 8;
650 i3 = (val & 0x000000ff);
652 u8 c0, c1, c2, c3;
653 c0 = ((i0 + i1 * 0xc1 + 0x18 + revid_0) ^ (i3 * i2 + 0x90)
654 ) & 0xff;
655 c1 = ((i1 + i2 + 0x90) ^ (c0 + i0 - 0xc1)
656 ) & 0xff;
657 c2 = ((i2 + 0xc8) ^ (c0 + ((revid_eth_0 + revid_0 * 0x23) ^ 0x19))
658 ) & 0xff;
659 c3 = ((i0 + 0xc1) ^ (i3 + ((revid_eth_1 + 0xc8) ^ 0x90))
660 ) & 0xff;
662 return ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3);
665 static void bba_devpoll(u16 *pstatus)
667 u8 status;
668 u32 ret;
669 s64 now;
671 UIP_LOG("bba_devpoll()\n");
673 now = gettime();
674 if(diff_msec(bba_arp_tmr,now)>=UIP_ARP_TMRINTERVAL) {
675 uip_arp_timer();
676 bba_arp_tmr = gettime();
679 ret = 0;
680 status = 0;
681 *pstatus = 0;
682 if(EXI_Lock(EXI_CHANNEL_0,EXI_DEVICE_2,NULL)==1) {
683 status = bba_cmd_in8(0x03);
684 if(status) {
685 bba_cmd_out8(0x02,BBA_CMD_IRMASKALL);
686 if(status&0x80) {
687 *pstatus |= (status<<8);
688 bba_interrupt(pstatus);
689 bba_cmd_out8(0x03,0x80);
690 bba_cmd_out8(0x02,BBA_CMD_IRMASKNONE);
691 EXI_Unlock(EXI_CHANNEL_0);
692 return;
694 if(status&0x40) {
695 *pstatus |= (status<<8);
696 __bba_init(bba_netif);
697 bba_cmd_out8(0x03, 0x40);
698 bba_cmd_out8(0x02,BBA_CMD_IRMASKNONE);
699 EXI_Unlock(EXI_CHANNEL_0);
700 return;
702 if(status&0x20) {
703 *pstatus |= (status<<8);
704 bba_cmd_out8(0x03, 0x20);
705 bba_cmd_out8(0x02,BBA_CMD_IRMASKNONE);
706 EXI_Unlock(EXI_CHANNEL_0);
707 return;
709 if(status&0x10) {
710 u32 response,challange;
712 *pstatus |= (status<<8);
713 bba_cmd_out8(0x05,bba_device.acstart);
714 bba_cmd_ins(0x08,&challange,sizeof(challange));
715 response = bba_calc_response(bba_netif,challange);
716 bba_cmd_outs(0x09,&response,sizeof(response));
717 bba_cmd_out8(0x03, 0x10);
718 bba_cmd_out8(0x02,BBA_CMD_IRMASKNONE);
719 EXI_Unlock(EXI_CHANNEL_0);
720 return;
722 if(status&0x08) {
723 *pstatus |= (status<<8);
724 bba_cmd_out8(0x03, 0x08);
725 bba_cmd_out8(0x02,BBA_CMD_IRMASKNONE);
726 EXI_Unlock(EXI_CHANNEL_0);
727 return;
730 *pstatus |= (status<<8);
731 bba_interrupt(pstatus);
732 bba_cmd_out8(0x02,BBA_CMD_IRMASKNONE);
734 EXI_Unlock(EXI_CHANNEL_0);
738 static s8_t __bba_start_tx(struct uip_netif *dev,struct uip_pbuf *p,struct uip_ip_addr *ipaddr)
740 return uip_arp_out(dev,ipaddr,p);
743 static s8_t __bba_link_tx(struct uip_netif *dev,struct uip_pbuf *p)
745 u8 pad[60];
746 u32 len;
747 struct uip_pbuf *tmp;
749 if(EXI_Lock(EXI_CHANNEL_0,EXI_DEVICE_2,NULL)==0) return UIP_ERR_IF;
751 if(p->tot_len>BBA_TX_MAX_PACKET_SIZE) {
752 UIP_LOG("__bba_link_tx: packet dropped due to big buffer.\n");
753 EXI_Unlock(EXI_CHANNEL_0);
754 return UIP_ERR_PKTSIZE;
757 if(!__linkstate()) {
758 EXI_Unlock(EXI_CHANNEL_0);
759 return UIP_ERR_ABRT;
762 while((bba_in8(BBA_NCRA)&(BBA_NCRA_ST0|BBA_NCRA_ST1)));
764 len = p->tot_len;
765 bba_out12(BBA_TXFIFOCNT,len);
767 bba_select();
768 bba_outsregister(BBA_WRTXFIFOD);
769 for(tmp=p;tmp!=NULL;tmp=tmp->next) {
770 bba_outsdata(tmp->payload,tmp->len);
772 if(len<BBA_MINPKTSIZE) {
773 len = (BBA_MINPKTSIZE-len);
774 bba_outsdata(pad,len);
776 bba_deselect();
778 bba_out8(BBA_NCRA,((bba_in8(BBA_NCRA)&~BBA_NCRA_ST0)|BBA_NCRA_ST1)); //&~BBA_NCRA_ST0
779 EXI_Unlock(EXI_CHANNEL_0);
780 return UIP_ERR_OK;
783 s8_t uip_bba_init(struct uip_netif *dev)
785 s8_t ret;
786 s32_t cnt;
788 ret = bba_probe(dev);
789 if(ret<0) return ret;
791 ret = bba_dochallengeresponse();
792 if(ret<0) return ret;
794 cnt = 0;
795 do {
796 udelay(500);
797 cnt++;
798 } while((ret=__bba_getlink_state_async())==0 && cnt<10000);
799 if(!ret) return UIP_ERR_IF;
801 dev->flags |= UIP_NETIF_FLAG_LINK_UP;
802 uip_netif_setup(dev);
803 uip_arp_init();
805 bba_recv_pbufs = NULL;
806 bba_arp_tmr = gettime();
808 return UIP_ERR_OK;
811 uipdev_s uip_bba_create(struct uip_netif *dev)
813 dev->name[0] = IFNAME0;
814 dev->name[1] = IFNAME1;
816 dev->output = __bba_start_tx;
817 dev->linkoutput = __bba_link_tx;
818 dev->mtu = 1500;
819 dev->flags = UIP_NETIF_FLAG_BROADCAST;
820 dev->hwaddr_len = 6;
822 bba_device.ethaddr = (struct uip_eth_addr*)dev->hwaddr;
823 bba_device.state = UIP_ERR_OK;
825 bba_netif = dev;
826 return &bba_device;
829 void uip_bba_poll(struct uip_netif *dev)
831 u16 status;
833 UIP_LOG("uip_bba_poll()\n");
835 bba_devpoll(&status);