Dm9000x. c

Source: Internet
Author: User

/*
* U-BOOT dm9000a driver
* Www.davicom.com.tw
*
* This program is loaded into SRAM in Bootstrap mode, where it waits
* For commands on uart1 to read and write memory, jump to Code etc.
* A design goal for this program is to be entirely independent of
* Target board. Anything with a CL-PS7111 or ep7211 shocould be able to run
* This code in Bootstrap mode. All the Board specifics can be handled on
* The host.
*
* This program is free software; you can redistribute it and/or modify
* It under the terms of the GNU General Public License as published
* The Free Software Foundation; either version 2 of the license, or
* (At your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* But without any warranty; without even the implied warranty
* Merchantability or fitness for a special purpose. See
* GNU General Public License for more details.
*
* You shoshould have written ed a copy of the GNU General Public License
* Along with this program; if not, write to the Free Software
* Foundation, inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* V1.01-load MAC address from EEPROM
*/

# Include <common. h>
# Include <command. h>
# Include <net. h>

# Ifdef config_driver_dm9000
# Include "dm9000x. H"

# Define dm9000_id 0x90000a46
# Define dm9010_id 0x90100a46
# Define dm9ks_reg05 (rxcr_discard_longpkt | rxcr_discard_crcpkt)
# Define dm9ks_disintr imr_sram_antoreturn
/*
* If your bus is 8-bit or 32-bit, you must modify below.
* Ex. Your bus is 8 bit
* Dm9000_pptr * (volatile u8 *) (dm9000_base)
*/

# Define dm9000_base config_dm9000_base

# Define dm9000_pptr * (volatile 2010*) (dm9000_io)
# Define dm9000_pdata * (volatile 2010*) (dm9000_data)

# Define mdelay (n) udelay (n) * 1000)

Static unsigned char ior (INT );
Static void Iow (INT, u8 );
Static void phy_write (INT, 2010 );
Static void move8 (unsigned char *, Int, INT );
Static void move16 (unsigned char *, Int, INT );
Static void move32 (unsigned char *, Int, INT );
Static 2010read_srom_word (INT );
Static void dmfe_init_dm9000 (void );
Static u32 getdm9000id (void );
Void dm9000_get_enetaddr (uchar *);
Static void eth_reset (void );
Void eth_halt (void );
Int eth_init (bd_t *);
Void (* movedata) (unsigned char *, Int, INT );

Static void Iow (INT Reg, u8 value)
{
Dm9000_pptr = reg;
Dm9000_pdata = Value & 0xff;
}

Static unsigned char ior (int reg)
{
Dm9000_pptr = reg;
Return dm9000_pdata & 0xff;
}

Static void phy_write (INT Reg, 2010value)
{
/* Fill the phyxcer Register into reg_0c */
Iow (dm9ks_epar, dm9ks_phy | REG );

/* Fill the written data into reg_0d & reg_0e */
Iow (dm9ks_epdrl, (Value & 0xff ));
Iow (dm9ks_epdrh, (value> 8) & 0xff ));

Iow (dm9ks_epcr, epcr_phy_sele | epcr_write);/* issue phyxcer write command */
Udelay (500);/* Wait write complete */
Iow (dm9ks_epcr, 0x0);/* clear phyxcer write command */
}

/*
Leng: Unit byte
Selec 0: input (RX) 1: output (TX)
If selec = 0, move data from FIFO to data_ptr
If selec = 1, move data from data_ptr to FIFO
*/
Static void move8 (unsigned char * data_ptr, int Leng, int selec)
{
Int I;
If (selec)
For (I = 0; I <Leng; I ++)
Dm9000_pdata = (data_ptr [I] & 0xff );
Else
For (I = 0; I <Leng; I ++)
Data_ptr [I] = dm9000_pdata;
}

Static void move16 (unsigned char * data_ptr, int Leng, int selec)
{
Int I, tmpleng;
Tmpleng = (Leng + 1)> 1;
If (selec)
For (I = 0; I <tmpleng; I ++)
Dm9000_pdata = (2010*) data_ptr) [I];
Else
For (I = 0; I <tmpleng; I ++)
(*) Data_ptr) [I] = dm9000_pdata;
}

Static void move32 (unsigned char * data_ptr, int Leng, int selec)
{
Int I, tmpleng;
Tmpleng = (Leng + 3)> 2;
If (selec)
For (I = 0; I <tmpleng; I ++)
Dm9000_pdata = (u32 *) data_ptr) [I];
Else
For (I = 0; I <tmpleng; I ++)
(U32 *) data_ptr) [I] = dm9000_pdata;
}

/*
* Read a word data from EEPROM
*/
Static 2010read_srom_word (INT offset)
{
Iow (dm9ks_epar, offset );
Iow (dm9ks_epcr, 0x4 );
Udelay (200 );
Iow (dm9ks_epcr, 0x0 );
Return (IOR (dm9ks_epdrl) + (IOR (dm9ks_epdrh) <8 ));
}
/*
* Initilize dm9000 Board
*/
Static void dmfe_init_dm9000 (void)
{
Int io_mode;

/* Set the internal PHY power-on, gpios normal, and wait 20 ms */
Iow (dm9ks_gpr, upl_phyup );
Mdelay (20);/* Wait for phy power-on ready */
Iow (dm9ks_gpr, upl_phydown);/* power-down PHY */
Mdelay( 1000);/* compatible with rtl8305s */
Iow (dm9ks_gpr, upl_phyup );
Mdelay (20);/* Wait for phy power-on ready */

Iow (dm9ks_ncr, ncr_mac_loopback | ncr_reset );
Udelay (20);/* Wait 20us at least for software reset OK */
Iow (dm9ks_ncr, ncr_mac_loopback | ncr_reset );
Udelay (20);/* Wait 20us at least for software reset OK */

/* I/O mode */
Io_mode = ior (dm9ks_isr)> 6;/* ISR bit7: 6 keeps I/O mode */
Switch (io_mode)
{
Case dm9ks_byte_mode:
Printf ("dm9000 work in 8 bus width \ n ");
Movedata = move8;
Break;
Case dm9ks_word_mode:
Printf ("dm9000 work in 16 bus width \ n ");
Movedata = move16;
Break;
Case dm9ks_dword_mode:
Printf ("dm9000 work in 32 bus width \ n ");
Movedata = move32;
Break;
Default:
Printf ("dm9000 work in wrong bus width, error \ n ");
Break;
}

/* Set PHY */
Phy_write (4, 0x01e1 );
Phy_write (0, 0x1200);/* n-way */

/* Program operating register */
Iow (dm9ks_ncr, 0 );
Iow (dm9ks_ctl, 0);/* TX polling clear */
Iow (dm9ks_bptr, 0x30 | jpt_600us);/* Less 3kb, 600us */
Iow (dm9ks_smcr, 0);/* special mode */
Iow (dm9ks_nsr, 0x2c);/* clear TX status */
Iow (dm9ks_isr, 0x0f);/* clear interrupt status */
Iow (dm9ks_tcr2, tcr2_ledmode1);/* Set led mode 1 */
# If 0
/* Data Bus current driving/sinking capability */
Iow (dm9ks_pbcr, 0x60);/* default: 8mA */
# Endif
 
Iow (0x1d, 0x80);/* receive broadcast packet */

/* Activate dm9000a/dm9010 */
Iow (dm9ks_rxcr, dm9ks_reg05 | rxcr_rxenable );
Iow (dm9ks_imr, dm9ks_disintr );
}

/* Packet page register access functions */
Static u32 getdm9000id (void)
{
U32 id_val;

Dm9000_pptr = dm9ks_pid_h;
Id_val = (dm9000_pdata & 0xff) <8;
Dm9000_pptr = dm9ks_pid_l;
Id_val + = (dm9000_pdata & 0xff );
Id_val = id_val <16;

Dm9000_pptr = dm9ks_vid_h;
Id_val + = (dm9000_pdata & 0xff) <8;
Dm9000_pptr = dm9ks_vid_l;
Id_val + = (dm9000_pdata & 0xff );

Return id_val;
}

Void dm9000_get_enetaddr (uchar * ADDR)
{
Int I;
U8 temp;
Eth_reset ();
Printf ("Mac :");
For (I = 0x10; I <= 0x15; I ++ ){
Temp = ior (I );
* ADDR ++ = temp;
Printf ("% x:", temp );
}

Return;
}

Static void eth_reset (void)
{
U32 ID;

Id = getdm9000id ();
If (ID! = Dm9000_id)
{
Printf ("not found the dm9000 ID: % x \ n", ID );
Return;
} Else
Printf ("found dm9000 ID: % x \ n", ID );
Eth_halt ();
Dmfe_init_dm9000 ();
}

Void eth_halt (void)
{
/* Reset devie */
Phy_write (0x00, 0x8000);/* PHY reset */
Iow (dm9ks_gpr, upl_phydown);/* power-down PHY */
Iow (dm9ks_imr, dm9ks_disintr);/* disable all interrupt */
Iow (dm9ks_rxcr, 0x00);/* disable RX */
}

Int eth_init (bd_t * BD)
{
U32 ID;
Int I, J;
+ + +;

Id = getdm9000id ();
If (ID! = Dm9000_id)
{
Printf ("not found the dm9000 ID: % x \ n", ID );
Return 1;
}
Printf ("found dm9000 ID: % x at address % x! \ N ", ID, dm9000_base );
Dmfe_init_dm9000 ();

{
Int env_size;
Char * s = NULL, * E = NULL;
Unsigned char env_mac [20];
Env_size = getenv_r ("ethaddr", env_mac, sizeof (env_mac ));
If (env_size! = 18)
{
Printf ("\ n *** error: ethaddr is not set properly !! \ N ");
# If 0
For (I = 0; I <3; I ++)/* read mac from EEPROM */
Mac [I] = read_srom_word (I );
# Else
Mac [0] = 0x1100;
Mac [1] = 0x3322;
Mac [2] = 0x5544;
# Endif
}
Else
{
S = env_mac;
For (I = 0; I <6; ++ I)
{
(BD-> bi_enetaddr) [I] = s? Simple_strtoul (S, & E, 16): 0;
If (s) S = (* E )? E + 1: E;
}
Printf ("BD-> bi_entaddr: % 02x: % 02x: % 02x: % 02x: % 02x: % 02x \ n", BD-> bi_enetaddr [0],
BD-> bi_enetaddr [1], BD-> bi_enetaddr [2], BD-> bi_enetaddr [3],
BD-> bi_enetaddr [4], BD-> bi_enetaddr [5]);
}
}
Printf ("[eth_init] Mac :");
For (I = 0, j = 0x10; I <6; I ++, J ++)
{
Iow (J, BD-> bi_enetaddr [I]);
Printf ("% x:", BD-> bi_enetaddr [I]);
}
Printf ("\ n ");

Return 0;
}

/* Get A data block via Ethernet */
Extern int eth_rx (void)
{
Unsigned short rxlen;
Unsigned char * ADDR = NULL;
U8 rxread;
Rx_t RX;
U8 * PTR = (u8 *) & RX;

Rxread = ior (dm9ks_mr1_x );
Rxread = ior (dm9ks_isr );
Rxread = ior (dm9ks_mr1_x) & 0xff;

If (rxread! = 1)/* No data */
Return 0;

Dm9000_pptr = dm9ks_mrcmd;/* set read PTR ++ */

/* Read packet Status & length */
Movedata (PTR, 4, 0 );

Rxlen = Rx. DESC. length;/* get len */

If (RX. DESC. Status & (rx_runtframe | rx_phyerr | rx_alignerr | rx_crcerr ))
Printf ("[dm9ks] RX error % x \ n", RX. DESC. status );

If (rxlen> pktsize_align + pktalign)
Printf ("Packet too big! % D \ n ", rxlen, pktsize_align + pktalign );

ADDR = (unsigned char *) netrxpackets [0];
Movedata (ADDR, rxlen, 0 );

/* Pass the packet up to the protocol layers .*/
Netreceive (netrxpackets [0], rxlen );

Return rxlen;
}

/* Send a data block via Ethernet .*/
Extern int eth_send (volatile void * packet, int length)
{
Volatile unsigned char * ADDR;
Int length1 = length;

Dm9000_pptr = dm9ks_mwcmd;/* data copy Ready Set */

/* Copy Data */
ADDR = packet;
Movedata (ADDR, length, 1 );

/* Set packet length */
Iow (dm9ks_txplh, (length1> 8) & 0xff );
Iow (dm9ks_txpll, length1 & 0xff );

/* Start transmit */
Iow (dm9ks_ctl, tcr_tx_request );

While (1)/* Wait For TX complete */
{
If (IOR (dm9ks_nsr) & (ns_tx2end | ns_tx1end ))
Break;
}
Return 0;
}

# Endif/* config_driver_dm9000 */

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.