diff -r -U 5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/devs/eth/cl/cs8900a/current/cdl/cl_cs8900a_eth_drivers.cdl devo/ecos/packages/devs/eth/cl/cs8900a/current/cdl/cl_cs8900a_eth_drivers.cdl --- clean/ecos/packages/devs/eth/cl/cs8900a/current/cdl/cl_cs8900a_eth_drivers.cdl 2005-05-08 12:29:39.000000000 +0300 +++ devo/ecos/packages/devs/eth/cl/cs8900a/current/cdl/cl_cs8900a_eth_drivers.cdl 2008-11-07 19:39:27.000000000 +0200 @@ -78,10 +78,26 @@ into the EEPROM associated with the interface, so that the new MAC address is permanently recorded. Doing this should be a carefully chosen decision, hence this option." } + cdl_option CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT { + display "8-bit data bus" + flavor bool + requires !CYGSEM_DEVS_ETH_CL_CS8900A_WRITE_EEPROM + requires CYGSEM_DEVS_ETH_CL_CS8900A_NOINTS + default_value 0 + description " + The CS8900A can been use in 8-bit mode. From AN181 from + Cirrus Logic... Unsupported functions in 8-bit mode: + Interrupts are not supported. Polled mode must be used; + The DMA engine only uses 16 bit memory access and does not + support 8 bit transfers; The packet page pointer has an + auto increment feature that cannot be used in 8-bit mode; + An EEPROM is not supported." + } + cdl_option CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED { display "Byte swapped data bus" flavor bool default_value 0 description " diff -r -U 5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/devs/eth/cl/cs8900a/current/ChangeLog devo/ecos/packages/devs/eth/cl/cs8900a/current/ChangeLog --- clean/ecos/packages/devs/eth/cl/cs8900a/current/ChangeLog 2007-09-11 20:37:22.000000000 +0300 +++ devo/ecos/packages/devs/eth/cl/cs8900a/current/ChangeLog 2008-11-07 19:43:43.000000000 +0200 @@ -1,5 +1,17 @@ +2008-11-07 Sergei Gavrikov + + * cdl/cl_cs8900a_eth_drivers.cdl: Added + CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT option to manage chip in 8-bit + mode. + * include/cs8900.h + * src/if_cs8900a.c: Added a support for the 8-bit access for CS8900A. + All access to CS8900A registers wrapped via CS_IN, CS_OUT macros (the + macros were defined in past, but, still not used). In common way the + macros use the eCos macros: HAL_READ_UINT16, HAL_WRITE_UINT16 , but, + in other (rare) conditions they can use 8-bit access too. + 2007-09-04 Stephen Finney * add timeout to potential infinite loop in cs8900a_send per bugzilla report 1000281 diff -r -U 5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/devs/eth/cl/cs8900a/current/include/cs8900.h devo/ecos/packages/devs/eth/cl/cs8900a/current/include/cs8900.h --- clean/ecos/packages/devs/eth/cl/cs8900a/current/include/cs8900.h 2005-11-23 23:26:50.000000000 +0200 +++ devo/ecos/packages/devs/eth/cl/cs8900a/current/include/cs8900.h 2008-11-07 19:39:27.000000000 +0200 @@ -78,11 +78,13 @@ // 0 disables all debug output // 1 for process debug output // 2 for added data IO output: get_reg, put_reg // 4 for packet allocation/free output // 8 for only startup status, so we can tell we're installed OK -#define DEBUG 0x0 +#ifndef DEBUG +# define DEBUG 0x0 +#endif #if DEBUG & 1 #define DEBUG_FUNCTION() do { diag_printf("%s\n", __FUNCTION__); } while (0) #define DEBUG_LINE() do { diag_printf("%d\n", __LINE__); } while (0) #else @@ -438,24 +440,24 @@ // "page pointer" access functions static __inline__ cyg_uint16 get_reg(cyg_addrword_t base, int regno) { cyg_uint16 val; - HAL_WRITE_UINT16(base+CS8900A_PPTR, regno); - HAL_READ_UINT16(base+CS8900A_PDATA, val); + CS_OUT(base, CS8900A_PPTR, regno); + CS_IN(base, CS8900A_PDATA, val); #if DEBUG & 2 - diag_printf("get_reg(%p, %d) => 0x%04x\n", base, regno, val); + diag_printf("get_reg(%p, %d) => 0x%04x\n", (void *)base, regno, val); #endif return val; } static __inline__ void put_reg(cyg_addrword_t base, int regno, cyg_uint16 val) { #if DEBUG & 2 - diag_printf("put_reg(%p, %d, 0x%04x)\n", base, regno, val); + diag_printf("put_reg(%p, %d, 0x%04x)\n", (void *)base, regno, val); #endif - HAL_WRITE_UINT16(base+CS8900A_PPTR, regno); - HAL_WRITE_UINT16(base+CS8900A_PDATA, val); + CS_OUT(base, CS8900A_PPTR, regno); + CS_OUT(base, CS8900A_PDATA, val); } #endif // _CYGONCE_ETH_CL_CS8900_H_ diff -r -U 5 -N -x CVS -x '*~' -x '.#*' clean/ecos/packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c devo/ecos/packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c --- clean/ecos/packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c 2007-09-11 20:37:23.000000000 +0300 +++ devo/ecos/packages/devs/eth/cl/cs8900a/current/src/if_cs8900a.c 2008-11-07 19:39:27.000000000 +0200 @@ -210,11 +210,11 @@ // MSB 8 bits. get_reg(base, PP_ChipID); chip_type = get_reg(base, PP_ChipID); chip_rev = get_reg(base, PP_ChipRev); #if DEBUG & 8 - diag_printf("CS8900A[%p] - type: 0x%04x, rev: 0x%04x\n", base, chip_type, chip_rev); + diag_printf("CS8900A[%p] - type: 0x%04x, rev: 0x%04x\n", (void *)base, chip_type, chip_rev); #endif if (chip_type != PP_ChipID_CL) { #if DEBUG & 8 diag_printf("CS8900 - invalid type (0x%04x), must be 0x630e\n", chip_type); #endif @@ -351,14 +351,16 @@ PP_BufCFG_TxCol | PP_BufCFG_Miss | PP_BufCFG_SWI); put_reg(base, PP_IntReg, PP_IntReg_IRQ0); // Only possibility put_reg(base, PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx); // Clear Interrupt Status Queue before enabling interrupts do { - HAL_READ_UINT16(cpd->base+CS8900A_ISQ, stat); + CS_IN(cpd->base, CS8900A_ISQ, stat); } while (stat != 0) ; cpd->txbusy = false; +#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT put_reg(base, PP_BusCtl, PP_BusCtl_EnableIRQ); +#endif } // This routine is called to perform special "control" opertions static int cs8900a_control(struct eth_drv_sc *sc, unsigned long key, void *data, int data_length) @@ -471,10 +473,11 @@ int i; int len; cyg_uint8 *data; cyg_uint16 saved_data = 0, *sdata; cyg_uint16 stat; + bool force_coping_by_byte; bool odd_byte = false; // Mark xmitter busy cpd->txbusy = true; cpd->txkey = key; @@ -485,10 +488,16 @@ // Start the xmit sequence #ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED total_len = CYG_SWAP16(total_len); #endif +#ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT + force_coping_by_byte = true; +#else + force_coping_by_byte = false; +#endif + // The hardware indicates that there are options as to when the actual // packet transmission will start wrt moving of data into the transmit // buffer. However, impirical results seem to indicate that if the // packet is large and transmission is allowed to start before the // entire packet has been pushed into the buffer, the hardware gets @@ -496,16 +505,16 @@ // This may be a case of the copy loop below being interrupted, e.g. // a system timer interrupt, and the hardware getting unhappy that // not all of the data was provided before the transmission should // have completed (i.e. buffer underrun). // For now, the solution is to not allow this overlap. - //HAL_WRITE_UINT16(cpd->base+CS8900A_TxCMD, PP_TxCmd_TxStart_5) + //CS_OUT(cpd->base, CS8900A_TxCMD, PP_TxCmd_TxStart_5) // Start only when all data sent to chip - HAL_WRITE_UINT16(cpd->base+CS8900A_TxCMD, PP_TxCmd_TxStart_Full); + CS_OUT(cpd->base, CS8900A_TxCMD, PP_TxCmd_TxStart_Full); - HAL_WRITE_UINT16(cpd->base+CS8900A_TxLEN, total_len); + CS_OUT(cpd->base, CS8900A_TxLEN, total_len); // Wait for controller ready signal { // add timeout per cs8900a bugzilla report 1000281 */ int timeout = 1000; @@ -537,24 +546,24 @@ #ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED saved_data |= *data++; #else saved_data |= ((cyg_uint16)*data++) << 8; #endif - HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data); + CS_OUT(cpd->base, CS8900A_RTDATA, saved_data); len--; odd_byte = false; } - if (((CYG_ADDRESS)data & 0x1) == 0) { + if (!force_coping_by_byte && ((CYG_ADDRESS)data & 0x1) == 0) { /* Aligned on 16-bit boundary, so output contiguous words. */ sdata = (cyg_uint16 *)data; while (len > 1) { // Make sure data get on the bus in Big Endian format #if((CYG_BYTEORDER == CYG_MSBFIRST) && defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED) || \ (CYG_BYTEORDER == CYG_LSBFIRST) && !defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED )) - HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, *sdata++); + CS_OUT(cpd->base, CS8900A_RTDATA, *sdata++); #else - HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, CYG_SWAP16(*sdata++)); + CS_OUT(cpd->base, CS8900A_RTDATA, CYG_SWAP16(*sdata++)); #endif len -= sizeof(cyg_uint16); } data = (cyg_uint8 *)sdata; } else { @@ -566,11 +575,11 @@ #ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED saved_data = ((cyg_uint16)*data++) | (saved_data << 8); #else saved_data |= ((cyg_uint16)*data++) << 8; #endif - HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data); + CS_OUT(cpd->base, CS8900A_RTDATA, saved_data); len -= sizeof(cyg_uint16); } } /* Save last byte, if necessary. */ if (len == 1) { @@ -583,11 +592,11 @@ odd_byte = true; } } } if (odd_byte) { - HAL_WRITE_UINT16(cpd->base+CS8900A_RTDATA, saved_data); + CS_OUT(cpd->base, CS8900A_RTDATA, saved_data); } } // This function is called when a packet has been received. It's job is // to prepare to unload the packet from the hardware. Once the length of @@ -601,12 +610,22 @@ cyg_addrword_t base = cpd->base; cyg_uint16 len; if(stat & PP_RxCFG_RxOK) { // Only start reading a message if one has been received - HAL_READ_UINT16(base+CS8900A_RTDATA, stat); - HAL_READ_UINT16(base+CS8900A_RTDATA, len); +#ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_8BIT + CS_IN(base, CS8900A_RTDATA, stat); + CS_IN(base, CS8900A_RTDATA, len); +#else + // From AN181 Using the Crystal CS8900A in 8-bit mode. + // Note: it is very important to read the RxStatus and RxLength high + // order byte first. + stat = *(volatile CYG_BYTE *)(base + CS8900A_RTDATA + 1) << 8; + stat |= *(volatile CYG_BYTE *)(base + CS8900A_RTDATA); + len = *(volatile CYG_BYTE *)(base + CS8900A_RTDATA + 1) << 8; + len |= *(volatile CYG_BYTE *)(base + CS8900A_RTDATA); +#endif #ifdef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED len = CYG_SWAP16(len); #endif @@ -637,11 +656,11 @@ for (i = 0; i < sg_len; i++) { data = (cyg_uint16 *)sg_list[i].buf; mlen = sg_list[i].len; while (mlen >= sizeof(*data)) { - HAL_READ_UINT16(base+CS8900A_RTDATA, val); + CS_IN(base, CS8900A_RTDATA, val); if (data) { #if((CYG_BYTEORDER == CYG_MSBFIRST) && defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED) || \ (CYG_BYTEORDER == CYG_LSBFIRST) && !defined(CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED )) *data++ = val; #else @@ -649,11 +668,11 @@ #endif } mlen -= sizeof(*data); } if (mlen) { - HAL_READ_UINT16(base+CS8900A_RTDATA, val); + CS_IN(base, CS8900A_RTDATA, val); #ifndef CYGIMP_DEVS_ETH_CL_CS8900A_DATABUS_BYTE_SWAPPED // last odd byte will be in the LSB cval = (cyg_uint8)(val); #elif(CYG_BYTEORDER == CYG_MSBFIRST) // last odd byte will be in the MSB @@ -697,11 +716,11 @@ { cyg_uint16 event; cs8900a_priv_data_t *cpd = (cs8900a_priv_data_t *)sc->driver_private; cyg_addrword_t base = cpd->base; - HAL_READ_UINT16(base+CS8900A_ISQ, event); + CS_IN(base, CS8900A_ISQ, event); while (event != 0) { switch (event & ISQ_EventMask) { case ISQ_RxEvent: cs8900a_RxEvent(sc, event); break; @@ -721,11 +740,11 @@ #if DEBUG & 1 diag_printf("%s: Unknown event: %x\n", __FUNCTION__, event); #endif break; } - HAL_READ_UINT16(base+CS8900A_ISQ, event); + CS_IN(base, CS8900A_ISQ, event); } CYGHWR_CL_CS8900A_PLF_INT_CLEAR(cpd); }