📄 rtl8150.c
字号:
rtl8150->dr.requesttype = RTL8150_REQT_WRITE;
rtl8150->dr.request = RTL8150_REQ_SET_REG;
rtl8150->dr.value = cpu_to_le16p( &indx );
rtl8150->dr.index = 0;
rtl8150->dr.length = rtl8150->ctrl_urb.transfer_buffer_length = cpu_to_le16p( &size );
FILL_CONTROL_URB( &rtl8150->ctrl_urb, rtl8150->usb,
usb_sndctrlpipe(rtl8150->usb,0),
(char *)&rtl8150->dr,
data, size, set_registers_callback, rtl8150 );
if ( (ret = usb_submit_urb( &rtl8150->ctrl_urb )) ) {
info( " set_registers: usb_submit_urb failed" );
err( __FUNCTION__ " BAD CTRL %d", ret);
return ret;
}
rtl8150->flags |= CTRL_URB_SLEEP;
/// marked by Owen on 01/11/2001
//interruptible_sleep_on( &rtl8150->ctrl_wait );
///info( "-set_registers()<=====" );
return ret;
}
static int read_phy_word( rtl8150_t *rtl8150, __u8 phy, __u8 indx, __u16 *regd )
{
int i;
__u8 MiiPhyAccessContent;
/*
set_register( rtl8150, MiiPhyAccess, 0 );
set_register( rtl8150, MiiPhyAddr, phy );
set_register( rtl8150, MiiPhyAccess, (0x40 | indx) );
for (i = 0; i < REG_TIMEOUT; i++)
{
get_registers( rtl8150, MiiPhyAccess, 1, &MiiPhyAccessContent );
if ( (MiiPhyAccessContent & 0x40) == 0)
break;
}
if ( i < REG_TIMEOUT )
{
get_registers( rtl8150, MiiPhyData, 2, regd );
return 0;
}
warn( __FUNCTION__ " failed" );
*/
return 1;
}
static int write_phy_word( rtl8150_t *rtl8150, __u8 phy, __u8 indx, __u16 regd )
{
int i;
__u8 data[2] = { 0, 0 };
__u8 MiiPhyAccessContent;
//info( "write_phy_word() =====>" );
/*
*data = cpu_to_le16p( ®d );
set_register( rtl8150, MiiPhyAccess, 0 );
set_register( rtl8150, MiiPhyAddr, phy );
set_registers( rtl8150, MiiPhyData, 2, data );
set_register( rtl8150, MiiPhyAccess, (0x60 | indx) );
for (i = 0; i < REG_TIMEOUT; i++)
{
get_registers( rtl8150, MiiPhyAccess, 1, &MiiPhyAccessContent );
if ( (MiiPhyAccessContent & 0x40) == 0)
break;
}
if ( i < REG_TIMEOUT )
return 0;
warn( __FUNCTION__ " failed" );
*/
return 1;
}
static int read_eprom_word( rtl8150_t *rtl8150, __u8 index, __u16 *retdata )
{
int i, tmp;
//info( "+read_eprom_word() =====>" );
while( rtl8150->get_registers_flag == 1 )
;
rtl8150->get_registers_flag = 1;
get_registers( rtl8150, index, 2, retdata );
while( rtl8150->get_registers_flag == 1 )
;
//info( "-read_eprom_word() <=====" );
return 0;
}
static int read_eprom_byte( rtl8150_t *rtl8150, __u16 index, __u8 *retdata )
{
int i, tmp;
//info( "+read_eprom_byte() =====>" );
while( rtl8150->get_registers_flag == 1 )
;
rtl8150->get_registers_flag = 1;
get_registers( rtl8150, index, 1, retdata );
while( rtl8150->get_registers_flag == 1 )
;
//info( "-read_eprom_byte() <=====");
return 0;
}
#ifdef RTL8150_WRITE_EEPROM
static inline void enable_eprom_write( rtl8150_t *rtl8150 )
{
__u8 tmp;
//info( "+enable_eprom_write() =====>" );
//info( "-enable_eprom_write() <=====" );
}
static inline void disable_eprom_write( rtl8150_t *rtl8150 )
{
__u8 tmp;
//info( "+disable_eprom_write() =====>" );
//info( "-disable_eprom_write() <=====" );
}
static int write_eprom_word( rtl8150_t *rtl8150, __u8 index, __u16 data )
{
int i, tmp;
__u8 d[4] = {0x3f, 0, 0, EPROM_WRITE};
//info( "+write_eprom_word() =====>" );
/*
set_registers( rtl8150, EpromOffset, 4, d );
enable_eprom_write( rtl8150 );
set_register( rtl8150, EpromOffset, index );
set_registers( rtl8150, EpromData, 2, &data );
set_register( rtl8150, EpromCtrl, EPROM_WRITE );
for ( i=0; i < REG_TIMEOUT; i++ ) {
get_registers( rtl8150, EpromCtrl, 1, &tmp );
if ( tmp & EPROM_DONE )
break;
}
disable_eprom_write( rtl8150 );
if ( i < REG_TIMEOUT )
return 0;
warn( __FUNCTION__ " failed" );
*/
//info( "-write_eprom_word <=====");
return -1;
}
#endif /* RTL8150_WRITE_EEPROM */
static inline void get_node_id( rtl8150_t *rtl8150, __u8 *id )
{
int i;
info( "+get_node_id() =====>" );
for (i=0; i < 6; i++)
{
while( rtl8150->get_registers_flag == 1 )
;
rtl8150->get_registers_flag = 1;
get_registers( rtl8150, IDR0+i, 1, &id[i] );
while( rtl8150->get_registers_flag == 1 )
;
}
info( "-get_node_id() <=====" );
}
static void set_ethernet_addr( rtl8150_t *rtl8150 )
{
__u8 node_id[6];
info( "+set_ethernet_addr() =====>" );
get_node_id(rtl8150, node_id);
memcpy( rtl8150->net->dev_addr, node_id, sizeof(node_id) );
info( " set_ethernet_addr: node id = %x %x %x %x %x %x",
node_id[0], node_id[1], node_id[2], node_id[3], node_id[4], node_id[5] );
info( "-set_ethernet_addr() <======" );
}
static inline int reset_mac( rtl8150_t *rtl8150 )
{
__u8 data = 0;
int i;
info( "+reset_mac() =====>" );
/// software reset
data = SOFT_RST;
///info( " reset_mac: before set_register(rtl8150, Command, data)" );
while( rtl8150->set_registers_flag == 1 )
;
rtl8150->set_registers_flag = 1;
set_registers(rtl8150, Command, 1, &data);
while( rtl8150->set_registers_flag == 1 )
;
///info( " reset_mac: after set_register( rtl8150, Command, data)" );
for (i = 0; i < REG_TIMEOUT; i++)
{
while( rtl8150->get_registers_flag == 1 )
;
rtl8150->get_registers_flag = 1;
get_registers(rtl8150, Command, 1, &data);
while( rtl8150->get_registers_flag == 1 )
;
if ( ~(data & SOFT_RST) )
{
break;
}
}
if ( i == REG_TIMEOUT )
{
info( " reset_mac: software reset failed" );
return 1;
}
info( "-reset_mac() <=====" );
return 0;
}
static int enable_net_traffic( struct net_device *dev, struct usb_device *usb )
{
__u16 linkpart, bmsr;
__u8 data[4];
__u8 byte_tmp = 0;
rtl8150_t *rtl8150 = dev->priv;
__u16 rx_config_content;
info("+enable_net_traffic() =====>");
/// check if link okay!
while( rtl8150->get_registers_flag == 1 )
;
rtl8150->get_registers_flag = 1;
get_registers( rtl8150, MediaStst, 1, &byte_tmp );
while( rtl8150->get_registers_flag == 1 )
;
info(" enable_net_traffic: MediaStst = 0x%x", byte_tmp);
if ( byte_tmp & LINK )
info(" enable_net_traffic: LINK ON");
else
info(" enable_net_traffic: LINK OFF");
/// software reset
/// byte_tmp = SOFT_RST;
///set_register( rtl8150, Command, 1, &byte_tmp );
/// set Transmit Configuration Register
///info(" enable_net_traffic: before setting Tx Config");
while( rtl8150->set_registers_flag == 1 )
;
rtl8150->set_registers_flag = 1;
byte_tmp = TXRR1 | TXRR0 | IFG1 | IFG0;
set_registers( rtl8150, TxConfig, 1, &byte_tmp);
while( rtl8150->set_registers_flag == 1)
;
///while( rtl8150->get_registers_flag == 1 )
/// ;
///rtl8150->get_registers_flag = 1;
///get_registers( rtl8150, TxConfig, 1, &byte_tmp );
///while( rtl8150->get_registers_flag == 1 )
/// ;
///info( "enable_net_traffic: TxConfig = 0x%x", byte_tmp );
///info(" enable_net_traffic: after setting Tx Config");
/// set Receive Configuration Register
///info(" enable_net_traffic: before setting Rx Config");
while( rtl8150->set_registers_flag == 1 )
;
rtl8150->set_registers_flag = 1;
rx_config_content = AM | AB | AD | AAM;
set_registers( rtl8150, RxConfig, 2, &rx_config_content );
while( rtl8150->set_registers_flag == 1 )
;
///info(" enable_net_traffic: after setting Rx Config");
/// enable Tx and Rx
///info(" enable_net_traffic: before enabling Tx and Rx" );
while( rtl8150->set_registers_flag == 1 )
;
rtl8150->set_registers_flag = 1;
byte_tmp = RE | TE;
set_registers( rtl8150, Command, 1, &byte_tmp );
while( rtl8150->set_registers_flag == 1 )
;
///info(" enable_net_traffic: after enabling Tx and Rx" );
///while( rtl8150->get_registers_flag == 1 )
/// ;
///rtl8150->get_registers_flag = 1;
///get_register( rtl8150, Command, &byte_tmp);
///while( rtl8150->get_registers_flag == 1 )
/// ;
///info(" enable_net_traffic: Command = 0x%x", byte_tmp );
info( "-enable_net_traffic() <=====");
return 0;
}
static void read_bulk_callback( struct urb *urb )
{
rtl8150_t *rtl8150 = urb->context;
struct net_device *net;
int count = urb->actual_length, res;
int rx_status;
struct sk_buff *skb;
__u16 pkt_len;
//info( "+read_bulk_callback() =====>" );
if ( !rtl8150 || !(rtl8150->flags & RTL8150_RUNNING) )
return;
net = rtl8150->net;
if ( !netif_device_present(net) )
return;
if ( rtl8150->flags & RTL8150_RX_BUSY )
{
rtl8150->stats.rx_errors++;
return;
}
rtl8150->flags |= RTL8150_RX_BUSY;
switch ( urb->status ) {
case USB_ST_NOERROR:
break;
case USB_ST_NORESPONSE:
info( " read_bulk_callback: NO RESPONSE" );
dbg( "reset MAC" );
rtl8150->flags &= ~RTL8150_RX_BUSY;
break;
default:
info( " read_bulk_callback: Rx status = 0x%x", urb->status);
dbg( "%s: RX status %d", net->name, urb->status );
goto goon;
}
pkt_len = count - 4;
//info(" read_bulk_callback: packet length = 0x%x", pkt_len );
//info(" read_bulk_callback: packet = %x %x %x %x %x %x %x %x %x %x %x %x", rtl8150->rx_buff[0], rtl8150->rx_buff[1],
// rtl8150->rx_buff[2], rtl8150->rx_buff[3], rtl8150->rx_buff[4], rtl8150->rx_buff[5],
// rtl8150->rx_buff[6], rtl8150->rx_buff[7], rtl8150->rx_buff[8], rtl8150->rx_buff[9],
// rtl8150->rx_buff[10], rtl8150->rx_buff[11] );
if ( !(skb = dev_alloc_skb(pkt_len+2)) ) /// why "pkt_len + 2"
goto goon;
skb->dev = net;
skb_reserve(skb, 2);
eth_copy_and_sum(skb, rtl8150->rx_buff, pkt_len, 0);
skb_put(skb, pkt_len);
/// in "Linux Device Drivers", the two statements above should be
/// "memcpy( skb_put( skb, pkt_len), rtl8150->rx_buff, pkt_len );"
skb->protocol = eth_type_trans(skb, net);
netif_rx(skb); /// call this system call to transfer the "skb" to the upper layer
rtl8150->stats.rx_packets++;
rtl8150->stats.rx_bytes += pkt_len;
goon:
FILL_BULK_URB( &rtl8150->rx_urb, rtl8150->usb,
usb_rcvbulkpipe(rtl8150->usb, 1),
rtl8150->rx_buff, RTL8150_MAX_MTU,
read_bulk_callback, rtl8150 );
if ( (res = usb_submit_urb(&rtl8150->rx_urb)) )
{
info( " read_bulk_callback: usb_submit_urb failed" );
warn( __FUNCTION__ " failed submint rx_urb %d", res);
}
rtl8150->flags &= ~RTL8150_RX_BUSY;
//info( "-read_bulk_callback() <=====");
}
static void write_bulk_callback( struct urb *urb )
{
rtl8150_t *rtl8150 = urb->context;
///info( "+write_bulk_callback() =====>" );
if ( !rtl8150 || !(rtl8150->flags & RTL8150_RUNNING) )
return;
if ( !netif_device_present(rtl8150->net) )
return;
if ( urb->status )
info("%s: TX status %d", rtl8150->net->name, urb->status);
netif_wake_queue( rtl8150->net );
///info( "-write_bulk_callback() <=====" );
}
#ifdef RTL8150_USE_INTR
static void intr_callback( struct urb *urb )
{
rtl8150_t *rtl8150 = urb->context;
struct net_device *net;
__u8 *d;
///info( "intr_callback() =====>" );
if ( !rtl8150 )
return;
d = urb->transfer_buffer;
net = rtl8150->net;
/// if ( d[0] & 0xfc ) {
/// rtl8150->stats.tx_errors++;
/// if ( d[0] & TX_UNDERRUN )
/// rtl8150->stats.tx_fifo_errors++;
/// if ( d[0] & (EXCESSIVE_COL | JABBER_TIMEOUT) )
/// rtl8150->stats.tx_aborted_errors++;
/// if ( d[0] & LATE_COL )
/// rtl8150->stats.tx_window_errors++;
/// if ( d[0] & (NO_CARRIER | LOSS_CARRIER) )
/// rtl8150->stats.tx_carrier_errors++;
/// }
switch ( urb->status )
{
case USB_ST_NOERROR:
break;
case USB_ST_URB_KILLED:
break;
default:
info("intr status %d", urb->status);
}
}
#endif
static void rtl8150_tx_timeout( struct net_device *net )
{
rtl8150_t *rtl8150 = net->priv;
info( "+rtl8150_tx_timeout() =====>" );
if ( !rtl8150 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -