mirror of https://github.com/ipxe/ipxe.git
195 lines
4.6 KiB
C
195 lines
4.6 KiB
C
#ifndef _DM96XX_H
|
|
#define _DM96XX_H
|
|
|
|
/** @file
|
|
*
|
|
* Davicom DM96xx USB Ethernet driver
|
|
*
|
|
*/
|
|
|
|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
|
|
|
#include <ipxe/usb.h>
|
|
#include <ipxe/usbnet.h>
|
|
#include <ipxe/if_ether.h>
|
|
|
|
/** Read register(s) */
|
|
#define DM96XX_READ_REGISTER \
|
|
( USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \
|
|
USB_REQUEST_TYPE ( 0x00 ) )
|
|
|
|
/** Write register(s) */
|
|
#define DM96XX_WRITE_REGISTER \
|
|
( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \
|
|
USB_REQUEST_TYPE ( 0x01 ) )
|
|
|
|
/** Write single register */
|
|
#define DM96XX_WRITE1_REGISTER \
|
|
( USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE | \
|
|
USB_REQUEST_TYPE ( 0x03 ) )
|
|
|
|
/** Network control register */
|
|
#define DM96XX_NCR 0x00
|
|
#define DM96XX_NCR_RST 0x01 /**< Software reset */
|
|
|
|
/** Network status register */
|
|
#define DM96XX_NSR 0x01
|
|
#define DM96XX_NSR_LINKST 0x40 /**< Link status */
|
|
|
|
/** Receive control register */
|
|
#define DM96XX_RCR 0x05
|
|
#define DM96XX_RCR_ALL 0x08 /**< Pass all multicast */
|
|
#define DM96XX_RCR_RUNT 0x04 /**< Pass runt packet */
|
|
#define DM96XX_RCR_PRMSC 0x02 /**< Promiscuous mode */
|
|
#define DM96XX_RCR_RXEN 0x01 /**< RX enable */
|
|
|
|
/** Receive status register */
|
|
#define DM96XX_RSR 0x06
|
|
#define DM96XX_RSR_MF 0x40 /**< Multicast frame */
|
|
|
|
/** PHY address registers */
|
|
#define DM96XX_PAR 0x10
|
|
|
|
/** Chip revision register */
|
|
#define DM96XX_CHIPR 0x2c
|
|
#define DM96XX_CHIPR_9601 0x00 /**< DM9601 */
|
|
#define DM96XX_CHIPR_9620 0x01 /**< DM9620 */
|
|
|
|
/** RX header control/status register (DM9620+ only) */
|
|
#define DM96XX_MODE_CTL 0x91
|
|
#define DM96XX_MODE_CTL_MODE 0x80 /**< 4-byte header mode */
|
|
|
|
/** DM96xx interrupt data */
|
|
struct dm96xx_interrupt {
|
|
/** Network status register */
|
|
uint8_t nsr;
|
|
/** Transmit status registers */
|
|
uint8_t tsr[2];
|
|
/** Receive status register */
|
|
uint8_t rsr;
|
|
/** Receive overflow counter register */
|
|
uint8_t rocr;
|
|
/** Receive packet counter */
|
|
uint8_t rxc;
|
|
/** Transmit packet counter */
|
|
uint8_t txc;
|
|
/** General purpose register */
|
|
uint8_t gpr;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** DM96xx receive header */
|
|
struct dm96xx_rx_header {
|
|
/** Packet status */
|
|
uint8_t rsr;
|
|
/** Packet length (excluding this header, including CRC) */
|
|
uint16_t len;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** DM96xx transmit header */
|
|
struct dm96xx_tx_header {
|
|
/** Packet length (excluding this header) */
|
|
uint16_t len;
|
|
} __attribute__ (( packed ));
|
|
|
|
/** A DM96xx network device */
|
|
struct dm96xx_device {
|
|
/** USB device */
|
|
struct usb_device *usb;
|
|
/** USB bus */
|
|
struct usb_bus *bus;
|
|
/** Network device */
|
|
struct net_device *netdev;
|
|
/** USB network device */
|
|
struct usbnet_device usbnet;
|
|
};
|
|
|
|
/**
|
|
* Read registers
|
|
*
|
|
* @v dm96xx DM96xx device
|
|
* @v offset Register offset
|
|
* @v data Data buffer
|
|
* @v len Length of data
|
|
* @ret rc Return status code
|
|
*/
|
|
static inline __attribute__ (( always_inline )) int
|
|
dm96xx_read_registers ( struct dm96xx_device *dm96xx, unsigned int offset,
|
|
void *data, size_t len ) {
|
|
|
|
return usb_control ( dm96xx->usb, DM96XX_READ_REGISTER, 0, offset,
|
|
data, len );
|
|
}
|
|
|
|
/**
|
|
* Read register
|
|
*
|
|
* @v dm96xx DM96xx device
|
|
* @v offset Register offset
|
|
* @ret value Register value, or negative error
|
|
*/
|
|
static inline __attribute__ (( always_inline )) int
|
|
dm96xx_read_register ( struct dm96xx_device *dm96xx, unsigned int offset ) {
|
|
uint8_t value;
|
|
int rc;
|
|
|
|
if ( ( rc = dm96xx_read_registers ( dm96xx, offset, &value,
|
|
sizeof ( value ) ) ) != 0 )
|
|
return rc;
|
|
return value;
|
|
}
|
|
|
|
/**
|
|
* Write registers
|
|
*
|
|
* @v dm96xx DM96xx device
|
|
* @v offset Register offset
|
|
* @v data Data buffer
|
|
* @v len Length of data
|
|
* @ret rc Return status code
|
|
*/
|
|
static inline __attribute__ (( always_inline )) int
|
|
dm96xx_write_registers ( struct dm96xx_device *dm96xx, unsigned int offset,
|
|
void *data, size_t len ) {
|
|
|
|
return usb_control ( dm96xx->usb, DM96XX_WRITE_REGISTER, 0, offset,
|
|
data, len );
|
|
}
|
|
|
|
/**
|
|
* Write register
|
|
*
|
|
* @v dm96xx DM96xx device
|
|
* @v offset Register offset
|
|
* @v value Register value
|
|
* @ret rc Return status code
|
|
*/
|
|
static inline __attribute__ (( always_inline )) int
|
|
dm96xx_write_register ( struct dm96xx_device *dm96xx, unsigned int offset,
|
|
uint8_t value ) {
|
|
|
|
return usb_control ( dm96xx->usb, DM96XX_WRITE1_REGISTER, value,
|
|
offset, NULL, 0 );
|
|
}
|
|
|
|
/** Reset delay (in microseconds) */
|
|
#define DM96XX_RESET_DELAY_US 10
|
|
|
|
/** Interrupt maximum fill level
|
|
*
|
|
* This is a policy decision.
|
|
*/
|
|
#define DM96XX_INTR_MAX_FILL 2
|
|
|
|
/** Bulk IN maximum fill level
|
|
*
|
|
* This is a policy decision.
|
|
*/
|
|
#define DM96XX_IN_MAX_FILL 8
|
|
|
|
/** Bulk IN buffer size */
|
|
#define DM96XX_IN_MTU \
|
|
( 4 /* DM96xx header */ + ETH_FRAME_LEN + \
|
|
4 /* possible VLAN header */ + 4 /* CRC */ )
|
|
|
|
#endif /* _DM96XX_H */
|