| #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 */ |