Initial cut of the open ath9k htc firmware.
[open-ath9k-htc-firmware.git] / target_firmware / magpie_fw_dev / build / magpie_1_1 / sboot / hif / gmac / hif_gmac.c
1 #include <adf_os_stdtypes.h>
2 #include <adf_os_types.h>
3
4 //#include <HIF_api.h>
5 #include <cmnos_api.h>
6
7 #include <Magpie_api.h>
8
9 #include <adf_os_util.h>
10 #include <adf_os_mem.h>
11 #include <adf_os_time.h>
12 #include <dma_lib.h>
13 #include "hif_gmac.h"
14
15
16
17 /**************************Constants******************************/
18 enum __gmac_msg_type{
19     GMAC_HST_QUERY = 0x0001,
20     GMAC_HST_REPLY = 0x0002,
21     GMAC_TGT_QUERY = 0x0003,
22     GMAC_TGT_REPLY = 0x0004
23 };
24
25 enum __magpie_regs{
26     MAG_REG_GPIO_OE     = 0x00052000,/*GPIO Output Enable*/
27     MAG_REG_RST         = 0x00050010,/*Magpie reset reg*/
28     MAG_REG_RST_AHB     = 0x00050018,/*Magpie AHB_ARB reset reg*/
29     MAG_REG_MII0_CTRL   = 0x00054100,/*Magpie MII0 Control reg*/
30     MAG_REG_STAT_CTRL   = 0x00054104,/*Magpie Status reg*/
31     MAG_REG_MDIO        = 0x00054200,/*Mapie MDIO register*/
32     MAG_REG_MDIO_CMD    = 0x00 + MAG_REG_MDIO,/*CMD register (0)*/
33     MAG_REG_MDIO_OWN    = 0x02 + MAG_REG_MDIO,/*OWN register (1)*/
34     /**
35      * XXX: Endianess inside the word & between words
36      */
37     MAG_REG_MDIO_ADDR0  = 0x04 + MAG_REG_MDIO,/*ADDR0 register (2)*/
38     MAG_REG_MDIO_ADDR1  = 0x06 + MAG_REG_MDIO,/*ADDR1 register (3)*/
39     MAG_REG_MDIO_WRITE0 = 0x08 + MAG_REG_MDIO,/*Data WRITE0 register (4)*/
40     MAG_REG_MDIO_WRITE1 = 0x0a + MAG_REG_MDIO,/*Data WRITE1 register (5)*/
41     MAG_REG_MDIO_READ0  = 0x0c + MAG_REG_MDIO,/*Data READ0 register (6)*/
42     MAG_REG_MDIO_READ1  = 0x0e + MAG_REG_MDIO,/*Data READ1 register (7)*/
43 };
44
45 enum __gmac_regs{
46     GMAC_REG_BASE       = 0x00060000,
47     GMAC_REG_MAC_CFG1   = 0x00 + GMAC_REG_BASE,/*MAC config 1*/
48     GMAC_REG_MAC_CFG2   = 0x04 + GMAC_REG_BASE,/*MAC config 2*/
49     GMAC_REG_IPG_IFG    = 0x08 + GMAC_REG_BASE,/*Inter-packet-gap*/
50     GMAC_REG_HALF_DPLX  = 0x0c + GMAC_REG_BASE,/*Half duplex*/
51     GMAC_REG_MAX_FRAME  = 0x10 + GMAC_REG_BASE,/*Max frame length*/
52     GMAC_REG_MII_CFG    = 0x20 + GMAC_REG_BASE,/*MII mgmt config*/
53     GMAC_REG_MII_CMD    = 0x24 + GMAC_REG_BASE,/*MII mgmt command*/
54     GMAC_REG_MII_ADDR   = 0x28 + GMAC_REG_BASE,/*MII mgmt address*/
55     GMAC_REG_MII_CTRL   = 0x2c + GMAC_REG_BASE,/*MII mgmt control*/
56     GMAC_REG_MII_STAT   = 0x30 + GMAC_REG_BASE,/*MII mgmt status*/
57     GMAC_REG_MII_PSTAT  = 0x34 + GMAC_REG_BASE,/*MII mgmt Phy status/ind*/
58     GMAC_REG_IF_CTRL    = 0x38 + GMAC_REG_BASE,/*Interface control*/
59     GMAC_REG_IF_STAT    = 0x3c + GMAC_REG_BASE,/*Interface status*/
60     GMAC_REG_MAC_ADDR1  = 0x40 + GMAC_REG_BASE,/*MAC address 1*/
61     GMAC_REG_MAC_ADDR2  = 0x44 + GMAC_REG_BASE,/*MAC address 2*/
62     GMAC_REG_FIFO_CFG0  = 0x48 + GMAC_REG_BASE,/*FIFO config reg0*/
63     GMAC_REG_FIFO_CFG1  = 0x4c + GMAC_REG_BASE,/*FIFO config reg1*/
64     GMAC_REG_FIFO_CFG2  = 0x50 + GMAC_REG_BASE,/*FIFO config reg2*/
65     GMAC_REG_FIFO_CFG3  = 0x54 + GMAC_REG_BASE,/*FIFO config reg3*/
66     GMAC_REG_FIFO_CFG4  = 0x58 + GMAC_REG_BASE,/*FIFO config reg4*/
67     GMAC_REG_FIFO_CFG5  = 0x5c + GMAC_REG_BASE,/*FIFO config reg5*/
68     GMAC_REG_FIFO_RAM0  = 0x60 + GMAC_REG_BASE,/*FIFO RAM access reg0*/
69     GMAC_REG_FIFO_RAM1  = 0x64 + GMAC_REG_BASE,/*FIFO RAM access reg1*/
70     GMAC_REG_FIFO_RAM2  = 0x68 + GMAC_REG_BASE,/*FIFO RAM access reg2*/
71     GMAC_REG_FIFO_RAM3  = 0x6c + GMAC_REG_BASE,/*FIFO RAM access reg3*/
72     GMAC_REG_FIFO_RAM4  = 0x70 + GMAC_REG_BASE,/*FIFO RAM access reg4*/
73     GMAC_REG_FIFO_RAM5  = 0x74 + GMAC_REG_BASE,/*FIFO RAM access reg5*/
74     GMAC_REG_FIFO_RAM6  = 0x78 + GMAC_REG_BASE,/*FIFO RAM access reg6*/
75     GMAC_REG_FIFO_RAM7  = 0x7c + GMAC_REG_BASE,/*FIFO RAM access reg7*/
76 };
77
78 enum  __mag_reg_rst{
79     RST_GMAC   = (1 << 9),/*Reset the GMAC */
80     RST_MII    = (3 << 11),/*Reset the MII*/
81     RST_OTHERS = 0x5df,/*Reset everybody other than GMAC & MII*/
82 };
83
84 enum __mag_reg_rst_ahb{
85     RST_AHB_GMAC = 0x1
86 };
87 enum __mag_mii0_ctrl{
88     MII0_CTRL_MODE  = (1 << 0),/*MII mode*/
89     MII0_CTRL_100   = (1 << 4),/*MII control address 100 Mbps*/
90 };
91
92 enum __mag_mdio_cmd{
93     MDIO_CMD_DONE     = 0x01,/*Operation over*/
94     MDIO_CMD_WRITE    = 0x02,/*Write data*/
95     MDIO_CMD_READ     = 0x03 /*Read data*/
96 };
97 enum __mag_mdio_own{
98     MDIO_OWN_HST  = 0x00,/*Host can use CMD & Data Regs*/
99     MDIO_OWN_TGT  = 0x01 /*Tgt can use CMD & Data Regs*/
100 };
101
102 enum __gmac_reg_mac_cfg1{
103     MAC_CFG1_TX_EN   = (1 << 0),/*TX enable*/
104     MAC_CFG1_RX_EN   = (1 << 2),/*RX enable*/
105     MAC_CFG1_TX_FLOW = (1 << 4),/*TX Flow control enable*/
106     MAC_CFG1_RX_FLOW = (1 << 5),/*RX Flow control enable*/
107     MAC_CFG1_LOOP_EN = (1 << 8),/*Enable loopback*/
108 };
109 enum __gmac_reg_mac_cfg2{
110     MAC_CFG2_FULL_DUP = (1 << 0),/*Enable Full Duplex*/
111     MAC_CFG2_PAD_CRC  = (1 << 2),/*Enable MAC based CRC insertion*/
112     MAC_CFG2_CHK_LEN  = (1 << 4),/*Check Length field*/
113     MAC_CFG2_HUGE_FRM = (1 << 5),/*Allow sending huge frames*/
114     MAC_CFG2_MII      = (1 << 8),/*MAC is MII in mode*/
115     MAC_CFG2_GMII     = (1 << 9),/*MAC is in GMII mode*/
116     MAC_CFG2_PREAMBLE = (7 << 12),/*Default Preamble Length*/
117 };
118 enum __gmac_reg_mii_cfg{
119     MII_CFG_CLK_2MHZ  = 0x0006,/*Clock is 2Mhz*/ 
120 };
121 enum __gmac_reg_mii_addr{
122     MII_ADDR_RESET     = 0x000,/*Flush the MII address register*/
123     MII_ADDR_PHY_REG   = 0x011,/*Phy Status Reg*/
124 };
125 enum __gmac_reg_mii_ctrl{
126     MII_CTRL_FULL_DPLX = 0x0100,/*Full Duplex mode*/
127     MII_CTRL_SPEED_100 = 0x2000,/*Link Speed 100 Mbps*/
128     MII_CTRL_LOOPBACK  = 0x4000,/*Enable Loopback mode at PHY*/
129     MII_CTRL_RESET     = 0x8000,/*BMCR reset*/
130 };
131 enum __gma_reg_mii_cmd{
132     MII_CMD_WRITE  = 0x0,
133     MII_CMD_READ   = 0x1,/*Perform a Read cycle*/
134 };
135 enum __gmac_reg_fifo_cfg0{
136     FIFO_CFG0_EN   = 0x1f00,/*Enable all the Fifo module*/
137 };
138 enum __gmac_reg_fifo_cfg1{
139     FIFO_CFG1_SIZE_2K = (0x7ff << 16),/*Fifo size is 2K*/
140 };
141 enum __gmac_reg_fifo_cfg4{
142     FIFO_CFG4_RX_ALL = 0x3ffff,/*receive all frames*/
143 };
144 enum __gmac_reg_if_ctrl{
145     IF_CTRL_SPEED_100  = (1 << 16),/*Interface speed 100 Mbps for MII*/ 
146 };
147
148 /*************************GMAC Data types*******************************/
149 typedef enum __gmac_pkt_type{
150     GMAC_PKT_IS_BCAST,
151     GMAC_PKT_IS_UCAST
152 }__gmac_pkt_type_t;
153
154 struct __ethhdr{
155     unsigned char   dst[ETH_ALEN];/*destination eth addr */
156     unsigned char   src[ETH_ALEN]; /*source ether addr*/
157     A_UINT16      etype;/*ether type*/
158 }__attribute__((packed));
159 /**
160  * @brief this is will be in big endian format
161  */ 
162 struct __athhdr{
163 #ifdef LITTLE_ENDIAN
164     A_UINT8   proto:6,
165                 res:2;
166 #else                    
167     A_UINT8   res:2,
168                 proto:6;
169 #endif                
170     A_UINT8   res_lo;
171     A_UINT16  res_hi;
172 }__attribute__((packed));
173
174 typedef struct __gmac_hdr{
175     struct  __ethhdr   eth;
176     struct  __athhdr   ath;
177     A_UINT16         align_pad;/*pad it for 4 byte boundary*/
178 }__attribute__((packed))  __gmac_hdr_t;
179
180 /*********************************GMAC softC************************/
181
182 typedef struct __gmac_softc{
183     __gmac_hdr_t        hdr;
184     A_UINT16          gran;
185     HIF_CALLBACK        sw;
186 }__gmac_softc_t;
187
188
189 #define ret_pkt         sw.send_buf_done
190 #define indicate_pkt    sw.recv_buf
191 #define htc_ctx         sw.context
192 /*********************************DEFINES**********************************/
193 #define hif_gmac_sc(_hdl)   (__gmac_softc_t *)(_hdl)
194 #define gmac_hdr(_vbuf)     (__gmac_hdr_t *)(_vbuf)->desc_list->buf_addr
195 #define GMAC_HLEN           (sizeof(struct __gmac_hdr))
196
197 #define __gmac_mdelay(_msecs)   A_DELAY_USECS((_msecs) * 1000)
198
199 int     __gmac_xmit_buf(hif_handle_t hdl, int pipe, VBUF *vbuf);
200 void    __gmac_reap_recv(__gmac_softc_t  *sc, dma_engine_t  eng_no);
201
202 /***********************************Globals********************************/
203 /**
204  * @brief Engines are fixed
205  */
206 __gmac_softc_t    gmac_sc = {
207     .gran = GMAC_MAX_PKT_LEN
208 };
209 A_UINT8  gmac_addr[ETH_ALEN]  = {0x00, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa};
210 A_UINT8  bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
211
212 /**************************************APIs********************************/
213
214 /**
215  * @brief This a replica of the ADF_NBUF_ALLOC
216  * 
217  * @param size
218  * @param reserve
219  * @param align
220  * 
221  * @return VBUF*
222  */
223 VBUF *
224 __gmac_vbuf_alloc(A_UINT32  size, A_UINT32  reserve, A_UINT32 align)
225 {
226     VBUF *buf = NULL;
227     VDESC *desc;
228     
229     buf = VBUF_alloc_vbuf();
230     if ( buf != NULL ) {
231         desc = VDESC_alloc_vdesc();
232         desc->buf_addr = (A_UINT8 *)A_ALLOCRAM(size);
233         desc->buf_size = size;
234         desc->next_desc = NULL;
235         desc->data_offset = reserve;
236         desc->data_size = 0;
237         desc->control = 0;    
238         
239         buf->desc_list = desc;
240         buf->buf_length = 0;    
241     }
242     
243     return buf;
244 }
245 /**
246  * @brief This is a replica of ADF_NBUF_PULL_HEAD
247  * 
248  * @param buf
249  * @param size
250  * 
251  * @return A_UINT8*
252  */
253 A_UINT8 *
254 __gmac_vbuf_pull_head(VBUF  *buf, A_UINT32 len)
255 {
256     A_UINT8 *ptr = NULL;
257     VDESC *desc = buf->desc_list;
258     
259     desc->data_offset += len;
260     desc->data_size -= len;
261     buf->buf_length -= len;
262     ptr = desc->buf_addr + desc->data_offset;
263     
264     return ptr;
265 }
266 /**
267  * @brief This is a replica of ADF_NBUF_PUSH_HEAD
268  * 
269  * @param buf
270  * @param size
271  * 
272  * @return A_UINT8*
273  */
274 A_UINT8 *
275 __gmac_vbuf_push_head(VBUF *buf, A_UINT32 len)
276 {
277     A_UINT8 *ptr = NULL; 
278     VDESC *desc = buf->desc_list;
279     
280     desc->data_offset -= len;
281     desc->data_size += len;
282     buf->buf_length += len;
283     ptr = desc->buf_addr + desc->data_offset;
284     return(ptr);
285 }
286 /**
287  * @brief This is a replica ADF_NBUF_LAST
288  * 
289  * @param buf
290  * 
291  * @return VDESC*
292  */
293 VDESC * 
294 __gmac_vbuf_last(VBUF *buf)
295 {
296     VDESC *desc = buf->desc_list;
297     
298     while(desc->next_desc != NULL)
299         desc = desc->next_desc;
300     
301     return desc;
302 }
303 /**
304  * @brief This is a replica of ADF_NBUF_PUT_TAIL
305  * 
306  * @param buf
307  * @param size
308  * 
309  * @return A_UINT8*
310  */
311 A_UINT8 *
312 __gmac_vbuf_put_tail(VBUF  *buf, A_UINT32 len)
313 {
314     A_UINT8 *tail = NULL;
315     VDESC *last_desc = __gmac_vbuf_last(buf);
316     
317     tail = ( last_desc->buf_addr + last_desc->data_offset + 
318              last_desc->data_size );
319
320     last_desc->data_size += len;
321     buf->buf_length += len;
322     
323     return tail;
324 }
325
326 /************************************GMAC**********************************/
327 A_UINT16
328 __gmac_reg_read16(A_UINT32 addr)
329 {
330     return *((volatile A_UINT16 *)addr);
331 }
332
333 void
334 __gmac_reg_write16(A_UINT32 addr, A_UINT16 val)
335 {
336     *((volatile A_UINT16 *)addr) = val;
337 }
338
339
340 A_UINT32
341 __gmac_reg_read32(A_UINT32 addr)
342 {
343     return *((volatile A_UINT32 *)addr);
344 }
345
346 void
347 __gmac_reg_write32(A_UINT32 addr, A_UINT32 val)
348 {
349     *((volatile A_UINT32 *)addr) = val;
350 }
351 /**
352  * @brief Read the MAC address from EEPROM
353  * XXX: read from real EEPROM
354  * 
355  * @param mac (pointer to fill the mac address)
356  */
357 void
358 __gmac_rom_read_mac(A_UINT8  mac_addr[])
359 {
360     A_MEMCPY(mac_addr, gmac_addr, ETH_ALEN);
361 }
362 /**
363  * @brief Write the MAC address into the Station address
364  *        register
365  * 
366  * @param mac
367  */
368 void
369 __gmac_reg_write_mac(A_UINT8  mac_addr[])
370 {
371     A_UINT32  mac_lo = 0, mac_hi = 0;
372
373     A_MEMCPY(&mac_lo, mac_addr, 4);
374     A_MEMCPY(&mac_hi, mac_addr + 4, 2);
375
376     A_PRINTF("mac address = %x:%x:%x:%x:%x:%x\n",
377                  mac_addr[0], mac_addr[1], mac_addr[2],
378                  mac_addr[3], mac_addr[4], mac_addr[5]);
379
380     __gmac_reg_write32(GMAC_REG_MAC_ADDR1, mac_lo);
381     __gmac_reg_write32(GMAC_REG_MAC_ADDR2, mac_hi);
382 }
383
384 /**
385  * @brief Wait for the MII operation to complete
386  */
387 void
388 __gmac_mii_op_wait(void)
389 {
390     A_UINT32 r_data;
391
392     r_data = __gmac_reg_read32(GMAC_REG_MII_PSTAT) & 0x1;
393     while(r_data)
394          r_data = (__gmac_reg_read32(GMAC_REG_MII_PSTAT) & 0x1);
395
396 }
397 void
398 __gmac_reset(void)
399 {
400     volatile A_UINT32 r_data;
401     volatile A_UINT32 w_data;
402
403     /**
404      * Reset the GMAC controller from Magpie Reset Register
405      */
406     r_data = __gmac_reg_read32(MAG_REG_RST);
407     r_data |= RST_GMAC;
408     __gmac_reg_write32(MAG_REG_RST, r_data);
409
410     __gmac_mdelay(1);
411   
412     /**
413      * Pull it out from the Reset State
414      */
415     r_data  = __gmac_reg_read32(MAG_REG_RST);
416     r_data &= ~RST_GMAC;
417     __gmac_reg_write32(MAG_REG_RST, r_data);
418
419     /**
420      * Reset the MII
421      */
422     r_data  = __gmac_reg_read32(MAG_REG_RST);
423     r_data |= (RST_MII | RST_GMAC);
424     __gmac_reg_write32(MAG_REG_RST, r_data);
425
426     __gmac_mdelay(1);
427     /**
428      * Pull the MII out of reset
429      */
430     r_data  = __gmac_reg_read32(MAG_REG_RST);
431     r_data &= ~( RST_MII | RST_GMAC);
432     __gmac_reg_write32(MAG_REG_RST, r_data);
433
434     __gmac_mdelay(1);
435
436     /**
437      * Reset other modules PCI, PCIE, USB & Eth PLL
438      * XXX:why???
439      */
440 //    __gmac_reg_write32(MAG_REG_RST, RST_OTHERS);
441
442     __gmac_mdelay(1);
443
444     /**
445      * Reset the AHB Arb. Unit
446      */
447     r_data  = __gmac_reg_read32(MAG_REG_RST_AHB);
448     r_data |= RST_AHB_GMAC;
449     __gmac_reg_write32(MAG_REG_RST_AHB, r_data);
450     
451     /**
452      * MII mode initialization
453      */
454     w_data = ( MAC_CFG2_FULL_DUP | MAC_CFG2_PAD_CRC | MAC_CFG2_CHK_LEN |
455                MAC_CFG2_HUGE_FRM | MAC_CFG2_MII | MAC_CFG2_PREAMBLE );
456
457     __gmac_reg_write32(GMAC_REG_MAC_CFG2, w_data);
458
459     /**
460      * Enable  FIFO modules
461      */
462     __gmac_reg_write32(GMAC_REG_FIFO_CFG0, FIFO_CFG0_EN);
463
464     /**
465      * Mode = MII & Speed = 100 Mbps
466      */
467     w_data = ( MII0_CTRL_100 | MII0_CTRL_MODE );
468     __gmac_reg_write32(MAG_REG_MII0_CTRL, w_data);
469
470     /**
471      * Set the interface speed to 100 Mbps
472      */
473     __gmac_reg_write32(GMAC_REG_IF_CTRL, IF_CTRL_SPEED_100);
474
475     /**
476      * Fifo size set to 2K bytes
477      */
478     r_data  = __gmac_reg_read32(GMAC_REG_FIFO_CFG1);
479     r_data |= FIFO_CFG1_SIZE_2K;
480     __gmac_reg_write32(GMAC_REG_FIFO_CFG1, r_data);
481
482     /**
483      * Enable the transceiver
484      */
485     w_data = MAC_CFG1_RX_EN | MAC_CFG1_TX_EN;
486     __gmac_reg_write32(GMAC_REG_MAC_CFG1, w_data);
487
488     /**
489      * Set the MII Clock to 2Mhz
490      */
491     __gmac_reg_write32(GMAC_REG_MII_CFG, MII_CFG_CLK_2MHZ);
492
493     /**
494      * Programming the phy registers
495      */
496     __gmac_reg_write32(GMAC_REG_MII_ADDR, MII_ADDR_RESET);
497
498     /**
499      * BMCR reset for the PHY
500      */
501     __gmac_reg_write32(GMAC_REG_MII_CTRL, MII_CTRL_RESET);
502
503     /**
504      * Wait until the MII Reg write has been flushed
505      */
506     __gmac_mii_op_wait();
507
508     /**
509      * PHY register 0x000 , BMCR
510      */
511     __gmac_reg_write32(GMAC_REG_MII_ADDR, MII_ADDR_RESET);
512
513     /**
514      * Write the value in the register
515      */
516     w_data = ( MII_CTRL_FULL_DPLX | MII_CTRL_SPEED_100 | MII_CTRL_RESET);
517     __gmac_reg_write32(GMAC_REG_MII_CTRL, w_data);
518     
519     __gmac_mii_op_wait();
520
521     /**
522      * Pull the BMCR out of the reset state
523      */
524     __gmac_reg_write32(GMAC_REG_MII_ADDR, MII_ADDR_RESET);
525
526     w_data = (MII_CTRL_FULL_DPLX | MII_CTRL_SPEED_100);
527     __gmac_reg_write32(GMAC_REG_MII_ADDR, w_data);
528
529     __gmac_mii_op_wait();
530
531     /**
532      * XXX: This should be for some debugging purpose, don't know
533      * why we should write into the GPIO Output Enable the value
534      * returned from PHY status register Read
535      */
536     __gmac_reg_write32(GMAC_REG_MII_CMD, MII_CMD_WRITE);
537     __gmac_reg_write32(GMAC_REG_MII_ADDR, MII_ADDR_PHY_REG);
538     __gmac_reg_write32(GMAC_REG_MII_CMD, MII_CMD_READ);
539
540     __gmac_mii_op_wait();
541
542     r_data = __gmac_reg_read32(GMAC_REG_MII_STAT);
543
544     __gmac_reg_write32(MAG_REG_GPIO_OE, r_data);
545
546     /**
547      * Enable Receive Fifo
548      */
549     r_data  = __gmac_reg_read32(GMAC_REG_FIFO_CFG4);
550     r_data |= FIFO_CFG4_RX_ALL;
551     __gmac_reg_write32(GMAC_REG_FIFO_CFG4, r_data);
552
553 }
554 /**
555  * @brief return if the pipe is supported
556  * 
557  * @param pipe
558  * 
559  * @return a_bool_t
560  */
561 static inline a_bool_t
562 __gmac_chk_pipe(hif_gmac_pipe_t pipe)
563 {
564     switch (pipe) {
565     case HIF_GMAC_PIPE_TX:
566     case HIF_GMAC_PIPE_RX:
567         return A_TRUE;
568     default:
569         return A_FALSE;
570     }
571 }
572
573 VBUF *
574 __gmac_pkt_alloc(A_UINT32  size)
575 {
576     VBUF * buf;
577     A_UINT16 fill_size;
578     A_UINT8  *data;
579
580     if(size < GMAC_HLEN)
581         return NULL;
582
583     buf = __gmac_vbuf_alloc(size, GMAC_HLEN, 0);
584     if(!buf)
585         return NULL;
586
587     fill_size = size - GMAC_HLEN;
588
589     data = __gmac_vbuf_put_tail(buf, fill_size);
590
591     A_MEMSET(data, 0xaa, fill_size);
592
593     return buf;
594 }
595 /**
596  * @brief Slap the header
597  * 
598  * @param buf
599  * @param hdr
600  */
601 void
602 __gmac_put_hdr(VBUF * buf, __gmac_hdr_t  *hdr)
603 {
604     A_UINT8  *data;
605
606     data = __gmac_vbuf_push_head(buf, GMAC_HLEN);
607
608     A_MEMCPY(data, hdr, GMAC_HLEN);
609 }
610 /**
611  * @brief
612  * 
613  * @param hdr
614  * @param src
615  */
616 void
617 __gmac_prep_ethhdr(__gmac_hdr_t  *hdr, A_UINT8  *dst)
618 {
619     A_MEMCPY(hdr->eth.dst, dst, ETH_ALEN);
620     hdr->eth.etype = ETH_P_ATH;
621 }
622
623
624 a_bool_t
625 __is_ath_header(__gmac_softc_t  *sc, VBUF  *vbuf)
626 {
627     __gmac_hdr_t  *hdr = gmac_hdr(vbuf);
628     
629     if(hdr->ath.proto != sc->hdr.ath.proto)
630         return A_FALSE;
631     
632     return A_TRUE;
633 }
634
635 a_status_t
636 __gmac_process_discv(__gmac_softc_t  *sc)
637 {
638     a_status_t  err = A_STATUS_OK;
639     VBUF  *vbuf;
640     __gmac_hdr_t  *buf_hdr ;
641     
642           
643     vbuf = dma_lib_reap_recv(DMA_ENGINE_RX0);
644     
645     if(!__is_ath_header(sc, vbuf))
646         goto fail;
647     
648     buf_hdr = gmac_hdr(vbuf);    
649     
650     A_MEMCPY(sc->hdr.eth.dst, buf_hdr->eth.src, ETH_ALEN);
651     
652     __gmac_vbuf_pull_head(vbuf, GMAC_HLEN);
653
654     /**
655      * Application should do the return_recv
656      */       
657     sc->indicate_pkt(NULL, vbuf, sc->htc_ctx);
658     
659     
660     return A_STATUS_OK;
661
662     /**
663      * This is not our packet
664      */
665 fail:
666     
667     dma_lib_return_recv(DMA_ENGINE_RX0, vbuf);
668             
669     return err;     
670 }
671 /**
672  * @brief The GMAC host discovery loop
673  */
674 void
675 __gmac_discover(void)
676 {
677     a_status_t    err = A_STATUS_FAILED;
678     VBUF *    buf;
679     __gmac_softc_t  *sc = &gmac_sc;
680
681
682     /**
683      * Get a packet
684      */
685     buf = __gmac_pkt_alloc(GMAC_DISCV_PKT_SZ);
686
687     /**
688      * Prepare the broadcast packet
689      */
690     __gmac_prep_ethhdr(&sc->hdr, bcast_addr);
691     __gmac_put_hdr(buf, &sc->hdr);
692
693     while(1){
694
695         if(buf)
696             dma_lib_hard_xmit(DMA_ENGINE_TX0, buf);
697
698         buf = NULL;
699         __gmac_mdelay(GMAC_DISCV_WAIT);
700         
701         if(dma_lib_xmit_done(DMA_ENGINE_TX0))
702             buf = dma_lib_reap_xmitted(DMA_ENGINE_TX0);
703         
704         
705         while(dma_lib_recv_pkt(DMA_ENGINE_RX0) && err)
706             err = __gmac_process_discv(sc);
707
708         if(!err)
709             break;
710     }
711
712     adf_os_assert(buf);
713 }
714
715 void
716 __gmac_mdio_check(void)
717 {
718     A_UINT16  own;
719
720     /*Read the Ownership register*/
721     do {
722         own = __gmac_reg_read16(MAG_REG_MDIO_OWN);
723     } while ( own == MDIO_OWN_TGT );
724
725 }
726
727 void
728 __gmac_mdio_load_exec(void)
729 {
730     volatile A_UINT16  cmd, more = 1 ;
731     volatile A_UINT16  *addr[2];
732     void ( *exec_fn)(void) = NULL;
733
734     do {
735         /**
736          * Read the Command register
737          */
738         cmd = __gmac_reg_read16(MAG_REG_MDIO_CMD);
739
740         switch (cmd) {
741
742         case MDIO_CMD_WRITE:
743
744            /**
745             * 1. Read the address from Address register
746             * 2. Write the data from Data register into the address
747             */
748             (A_UINT16 *)addr[0]  = __gmac_reg_read16(MAG_REG_MDIO_ADDR0);
749             *addr[0] = __gmac_reg_read16(MAG_REG_MDIO_WRITE0);
750             
751             (A_UINT16 *)addr[1]  = __gmac_reg_read16(MAG_REG_MDIO_ADDR1);
752             *addr[1] = __gmac_reg_read16(MAG_REG_MDIO_WRITE1);
753
754             if ( exec_fn ) 
755                 break;
756
757             exec_fn = (A_UINT32 *)addr;
758             break;
759
760         case MDIO_CMD_DONE:
761
762             more = 0;
763             break;
764
765         case MDIO_CMD_READ:
766             
767             /**
768              * 1. Read the address from Address register
769              * 2. Write the data into the Data register from the address
770              */
771             addr[0]  = (A_UINT16 *)__gmac_reg_read16(MAG_REG_MDIO_ADDR0);
772              __gmac_reg_write16(MAG_REG_MDIO_READ0, *addr[0]);
773
774             addr[1]  = (A_UINT16 *)__gmac_reg_read16(MAG_REG_MDIO_ADDR1);
775             __gmac_reg_write16(MAG_REG_MDIO_READ1, *addr[1]);
776
777             break;
778         default:
779
780             A_PRINTF("Command not implemmented\n");
781             adf_os_assert(0);
782             break;
783         }
784
785     } while ( more );
786
787     /**
788      * Change the Ownership
789      */
790     __gmac_reg_write16(MAG_REG_MDIO_OWN, MDIO_OWN_HST);
791     
792     if ( exec_fn )
793         exec_fn();
794
795 }
796
797 void
798 __gmac_mdio_init(void)
799 {
800
801 more_exec:
802
803         /**
804          * Check for Targets turn
805          */
806         __gmac_mdio_check();
807
808         /**
809          * Load & execute or Read data, if this returns then keep
810          * repeating
811          */
812         __gmac_mdio_load_exec();
813
814         /**
815          * If we are here then Host wants some more function execs or
816          * reads
817          */
818         goto more_exec;
819
820 }
821 void
822 __gmac_boot_init(void)
823 {
824     __gmac_softc_t   *sc = &gmac_sc;
825     
826     
827     __gmac_reset();
828
829     /**
830      * Magpie is Booting
831      */
832     sc->hdr.ath.proto = ATH_P_MAGBOOT;
833
834     dma_lib_tx_init(DMA_ENGINE_TX0, DMA_IF_GMAC);
835     dma_lib_rx_init(DMA_ENGINE_RX0, DMA_IF_GMAC);
836
837     dma_lib_rx_config(DMA_ENGINE_RX0, GMAC_MAX_DESC, GMAC_MAX_PKT_LEN);
838
839     /**
840      * Read the MAC address from the ROM & Write it into the
841      * Register
842      */ 
843     __gmac_rom_read_mac(sc->hdr.eth.src);
844     __gmac_reg_write_mac(sc->hdr.eth.src);
845
846     /**
847      * Discover the Host
848      */
849     __gmac_discover();
850 }   
851 /**
852  * @brief
853  * 
854  * @param pConfig
855  * 
856  * @return hif_handle_t
857  */
858 hif_handle_t 
859 __gmac_init(HIF_CONFIG *pConfig)
860 {
861     __gmac_softc_t  *sc = &gmac_sc;
862     
863     sc->hdr.ath.proto = ATH_P_MAGNORM;
864
865     dma_lib_tx_init(DMA_ENGINE_TX0, DMA_IF_GMAC);
866     dma_lib_rx_init(DMA_ENGINE_RX0, DMA_IF_GMAC);
867     
868     return &gmac_sc;
869 }
870 /**
871  * @brief Configure the receive pipe
872  * 
873  * @param hdl
874  * @param pipe
875  * @param num_desc
876  */
877 void
878 __gmac_cfg_pipe(hif_handle_t hdl, int pipe, int num_desc)
879 {
880     __gmac_softc_t  *sc = &gmac_sc;
881
882     if(pipe == HIF_GMAC_PIPE_RX)
883         dma_lib_rx_config(DMA_ENGINE_RX0, num_desc, sc->gran);
884 }
885 /**
886  * @brief Start the interface
887  * 
888  * @param hdl
889  */
890 void
891 __gmac_start(hif_handle_t  hdl)
892 {
893     return;
894 }
895 /**
896  * @brief Register callback of thre HTC
897  * 
898  * @param hdl
899  * @param sw
900  */
901 void
902 __gmac_reg_callback(hif_handle_t hdl, HIF_CALLBACK *sw)
903 {
904     __gmac_softc_t   *sc = &gmac_sc;
905
906     sc->htc_ctx       = sw->context;
907     sc->indicate_pkt  = sw->recv_buf;
908     sc->ret_pkt       = sw->send_buf_done;
909 }
910 /**
911  * @brief reap the transmit queue for trasnmitted packets
912  * 
913  * @param sc
914  * @param eng_no
915  */
916 void
917 __gmac_reap_xmitted(__gmac_softc_t  *sc, dma_engine_t  eng_no)
918 {
919     VBUF *vbuf = NULL;
920     /**
921      * Walk through the all your TX engines
922      */
923     do {
924        
925        vbuf = dma_lib_reap_xmitted(eng_no);
926        if(!vbuf)
927             break;
928        
929        __gmac_vbuf_pull_head(vbuf, GMAC_HLEN);
930        sc->ret_pkt(vbuf, sc->htc_ctx);
931
932     } while ( vbuf );
933 }
934 /**
935  * @brief reap the receive queue for vbuf's on the specified
936  *        engine number
937  * 
938  * @param sc
939  * @param eng_no
940  */
941 void
942 __gmac_reap_recv(__gmac_softc_t  *sc, dma_engine_t  eng_no)
943 {
944     VBUF   *vbuf = NULL;
945
946     do {
947         vbuf = dma_lib_reap_recv(eng_no);
948         
949         if(!vbuf)
950             break;
951         
952         if(!__is_ath_header(sc, vbuf)){
953             dma_lib_return_recv(eng_no, vbuf);
954             continue;
955         }
956             
957         __gmac_vbuf_pull_head(vbuf, GMAC_HLEN);
958
959         sc->indicate_pkt(NULL, vbuf, sc->htc_ctx); 
960
961     } while ( vbuf );
962 }
963 /**
964  * @brief The interrupt handler
965  * 
966  * @param hdl
967  */
968 void
969 __gmac_isr_handler(hif_handle_t hdl)
970 {
971     __gmac_softc_t  *sc = &gmac_sc;
972
973     if(dma_lib_xmit_done(DMA_ENGINE_TX0))
974         __gmac_reap_xmitted(sc, DMA_ENGINE_TX0);
975
976     if(dma_lib_recv_pkt(DMA_ENGINE_RX0))
977         __gmac_reap_recv(sc, DMA_ENGINE_RX0);
978 }
979 /**
980  * @brief transmit the vbuf from the specified pipe
981  * 
982  * @param hdl
983  * @param pipe
984  * @param buf
985  * 
986  * @return int
987  */
988 int
989 __gmac_xmit_buf(hif_handle_t hdl, int pipe, VBUF *vbuf)
990 {
991     __gmac_softc_t  *sc = &gmac_sc;
992
993     if (pipe != HIF_GMAC_PIPE_TX)
994         return -1;
995
996 #if 0
997     adf_os_assert( vbuf->desc_list->data_offset >= GMAC_HLEN)
998 #endif
999      
1000     __gmac_put_hdr(vbuf, &sc->hdr);
1001
1002     return dma_lib_hard_xmit(DMA_ENGINE_TX0, vbuf);
1003 }
1004 /**
1005  * @brief Submit the receive vbuf into the receive queue
1006  * 
1007  * @param handle
1008  * @param pipe
1009  * @param buf
1010  */
1011 void
1012 __gmac_return_recv(hif_handle_t hdl, int pipe, VBUF *vbuf)
1013 {
1014     if (pipe == HIF_GMAC_PIPE_RX) 
1015         dma_lib_return_recv(DMA_ENGINE_RX0, vbuf);
1016 }
1017 /**
1018  * @brief Is this pipe number supported
1019  * 
1020  * @param handle
1021  * @param pipe
1022  * 
1023  * @return int
1024  */
1025 int
1026 __gmac_is_pipe_supported(hif_handle_t hdl, int pipe)
1027 {
1028     return __gmac_chk_pipe(pipe);
1029 }
1030 /**
1031  * @brief maximum message length this pipe can support
1032  * 
1033  * @param handle
1034  * @param pipe
1035  * 
1036  * @return int
1037  */
1038 int  
1039 __gmac_get_max_msg_len(hif_handle_t hdl, int pipe)
1040 {
1041     if(__gmac_chk_pipe(pipe))
1042         return GMAC_MAX_PKT_LEN;
1043
1044     return 0;
1045 }
1046 /**
1047  * @brief return the header room required by this HIF
1048  * 
1049  * @param hdl
1050  * 
1051  * @return int
1052  */
1053 int
1054 __gmac_get_reserved_headroom(hif_handle_t  hdl)
1055 {
1056     return (GMAC_HLEN);
1057 }
1058 /**
1059  * @brief Device shutdown, HIF reset required
1060  * 
1061  * @param hdl
1062  */
1063 void
1064 __gmac_shutdown(hif_handle_t hdl)
1065 {
1066     return;
1067 }
1068 void 
1069 __gmac_get_def_pipe(hif_handle_t handle, A_UINT8 *pipe_uplink, 
1070                        A_UINT8 *pipe_downlink)
1071 {
1072     *pipe_uplink   = HIF_GMAC_PIPE_RX;
1073     *pipe_downlink = HIF_GMAC_PIPE_TX;
1074 }
1075
1076 /**
1077  * @brief This install the API's of the HIF
1078  * 
1079  * @param apis
1080  */
1081 void 
1082 hif_gmac_module_install(struct hif_api *apis)
1083 {
1084     /* hook in APIs */
1085     apis->_init = __gmac_init;
1086     apis->_start = __gmac_start;
1087     apis->_config_pipe = __gmac_cfg_pipe;
1088     apis->_isr_handler = __gmac_isr_handler;
1089     apis->_send_buffer = __gmac_xmit_buf;
1090     apis->_return_recv_buf = __gmac_return_recv;
1091     apis->_is_pipe_supported = __gmac_is_pipe_supported;
1092     apis->_get_max_msg_len = __gmac_get_max_msg_len;
1093     apis->_register_callback = __gmac_reg_callback;
1094     apis->_shutdown = __gmac_shutdown;/*XXX*/
1095     apis->_get_reserved_headroom = __gmac_get_reserved_headroom;
1096     apis->_get_default_pipe  = __gmac_get_def_pipe;
1097 }
1098
1099 void 
1100 cmnos_gmac_module_install(struct gmac_api *boot_apis)
1101 {
1102     boot_apis->gmac_boot_init  = __gmac_boot_init;
1103 }