#ifndef _DM96XX_H #define _DM96XX_H /** @file * * Davicom DM96xx USB Ethernet driver * */ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include /** 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 */