diff options
Diffstat (limited to 'qemu/roms/ipxe/src/drivers/net/dm96xx.h')
-rw-r--r-- | qemu/roms/ipxe/src/drivers/net/dm96xx.h | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/qemu/roms/ipxe/src/drivers/net/dm96xx.h b/qemu/roms/ipxe/src/drivers/net/dm96xx.h new file mode 100644 index 000000000..43a1a4e30 --- /dev/null +++ b/qemu/roms/ipxe/src/drivers/net/dm96xx.h @@ -0,0 +1,194 @@ +#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 */ |