1
0
mirror of https://github.com/mist-devel/mist-firmware.git synced 2026-01-11 23:43:04 +00:00

Ethernet driver progress and competition pro usb support

This commit is contained in:
harbaum 2014-04-05 18:55:52 +00:00
parent 57d45c91de
commit 73e7f4cad4
21 changed files with 665 additions and 402 deletions

View File

@ -62,70 +62,76 @@ void cdc_control_poll(void) {
// low level usb handling happens inside usb_cdc_poll
if(usb_cdc_poll()) {
char key;
uint16_t read, i;
char data[AT91C_EP_OUT_SIZE];
// check for user input
if(usb_cdc_read(&key, 1)) {
if((read = usb_cdc_read(data, AT91C_EP_OUT_SIZE)) != 0) {
switch(tos_get_cdc_control_redirect()) {
case CDC_REDIRECT_RS232:
user_io_serial_tx(key);
iprintf("RS232 forward:\n");
hexdump(data, read, 0);
user_io_serial_tx(data, read);
break;
case CDC_REDIRECT_CONTROL:
// force lower case
if((key >= 'A') && (key <= 'Z'))
key = key - 'A' + 'a';
switch(key) {
case '\r':
cdc_puts("\n\033[7m <<< MIST board controller >>> \033[0m");
cdc_puts("Firmware version ATH" VDATE);
cdc_puts("Commands:");
cdc_puts("\033[7mR\033[0meset");
cdc_puts("\033[7mC\033[0moldreset");
cdc_puts("\033[7mD\033[0mebug output redirect");
cdc_puts("R\033[7mS\033[0m232 redirect");
cdc_puts("\033[7mP\033[0marallel redirect");
cdc_puts("\033[7mM\033[0mIDI redirect");
cdc_puts("");
break;
for(i=0;i<read;i++) {
// force lower case
if((data[i] >= 'A') && (data[i] <= 'Z'))
data[i] = data[i] - 'A' + 'a';
case 'r':
cdc_puts("Reset ...");
tos_reset(0);
switch(data[i]) {
case '\r':
cdc_puts("\n\033[7m <<< MIST board controller >>> \033[0m");
cdc_puts("Firmware version ATH" VDATE);
cdc_puts("Commands:");
cdc_puts("\033[7mR\033[0meset");
cdc_puts("\033[7mC\033[0moldreset");
cdc_puts("\033[7mD\033[0mebug output redirect");
cdc_puts("R\033[7mS\033[0m232 redirect");
cdc_puts("\033[7mP\033[0marallel redirect");
cdc_puts("\033[7mM\033[0mIDI redirect");
cdc_puts("");
break;
case 'r':
cdc_puts("Reset ...");
tos_reset(0);
break;
case 'c':
cdc_puts("Coldreset ...");
tos_reset(1);
break;
case 'd':
cdc_puts("Debug output redirect enabled");
tos_set_cdc_control_redirect(CDC_REDIRECT_DEBUG);
break;
case 's':
cdc_puts("RS232 redirect enabled");
tos_set_cdc_control_redirect(CDC_REDIRECT_RS232);
break;
case 'p':
cdc_puts("Parallel redirect enabled");
tos_set_cdc_control_redirect(CDC_REDIRECT_PARALLEL);
break;
case 'm':
cdc_puts("MIDI redirect enabled");
tos_set_cdc_control_redirect(CDC_REDIRECT_MIDI);
break;
}
break;
case 'c':
cdc_puts("Coldreset ...");
tos_reset(1);
break;
case 'd':
cdc_puts("Debug output redirect enabled");
tos_set_cdc_control_redirect(CDC_REDIRECT_DEBUG);
break;
case 's':
cdc_puts("RS232 redirect enabled");
tos_set_cdc_control_redirect(CDC_REDIRECT_RS232);
break;
case 'p':
cdc_puts("Parallel redirect enabled");
tos_set_cdc_control_redirect(CDC_REDIRECT_PARALLEL);
break;
case 'm':
cdc_puts("MIDI redirect enabled");
tos_set_cdc_control_redirect(CDC_REDIRECT_MIDI);
break;
}
break;
default:
break;
default:
break;
}
}
}

View File

@ -32,12 +32,6 @@ typedef unsigned int uint;
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#define AT91C_EP_IN_SIZE 0x40
#define AT91C_EP_OUT 1
#define AT91C_EP_OUT_SIZE 0x40
#define AT91C_EP_IN 2
#define WORD(a) (a)&0xff, ((a)>>8)&0xff
// Private members
@ -293,8 +287,8 @@ uchar usb_cdc_is_configured(void) {
//* \fn usb_cdc_read
//* \brief Read available data from Endpoint OUT
//*----------------------------------------------------------------------------
uint usb_cdc_read(char *pData, uint length) {
uint packetSize, nbBytesRcv = 0;
uint16_t usb_cdc_read(char *pData, uint16_t length) {
uint16_t packetSize, nbBytesRcv = 0;
if ( !usb_cdc_is_configured() )
return 0;

View File

@ -15,10 +15,18 @@
#ifndef CDC_ENUMERATE_H
#define CDC_ENUMERATE_H
#include <inttypes.h>
#define AT91C_EP_OUT_SIZE 0x40
#define AT91C_EP_OUT 1
#define AT91C_EP_IN_SIZE 0x40
#define AT91C_EP_IN 2
void usb_cdc_open(void);
unsigned char usb_cdc_is_configured(void);
unsigned int usb_cdc_write(const char *pData, unsigned int length);
unsigned int usb_cdc_read(char *pData, unsigned int length);
uint16_t usb_cdc_read(char *pData, uint16_t length);
#define usb_cdc_poll() usb_cdc_is_configured()

View File

@ -2,6 +2,8 @@
#ifndef DEBUG_H
#define DEBUG_H
#include "hardware.h"
// ------------ usb debugging -----------
#if 1

View File

@ -105,6 +105,28 @@ void __init_hardware(void)
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOA;
}
void hexdump(void *data, uint16_t size, uint16_t offset) {
uint8_t i, b2c;
uint16_t n=0;
char *ptr = data;
if(!size) return;
while(size>0) {
iprintf("%04x: ", n + offset);
b2c = (size>16)?16:size;
for(i=0;i<b2c;i++) iprintf("%02x ", 0xff&ptr[i]);
iprintf(" ");
for(i=0;i<(16-b2c);i++) iprintf(" ");
for(i=0;i<b2c;i++) iprintf("%c", isprint(ptr[i])?ptr[i]:'.');
iprintf("\n");
ptr += b2c;
size -= b2c;
n += b2c;
}
}
// A buffer of 256 bytes makes index handling pretty trivial
volatile static unsigned char tx_buf[256];
volatile static unsigned char tx_rptr, tx_wptr;
@ -144,10 +166,15 @@ void Usart0IrqHandler(void) {
// check usart rx buffer for data
void USART_Poll(void) {
while(rx_wptr != rx_rptr) {
// this can a little be optimized by sending whole buffer parts
// at once and not just single bytes. But that's probably not
// worth the effort.
char chr = rx_buf[rx_rptr++];
iprintf("USART RX %d (%c)\n", rx_buf[rx_rptr], rx_buf[rx_rptr]);
// data available -> send via user_io to core
user_io_serial_tx(rx_buf[rx_rptr++]);
user_io_serial_tx(&chr, 1);
}
}

View File

@ -3,6 +3,8 @@
#ifndef HARDWARE_H
#define HARDWARE_H
#include <inttypes.h>
#define MCLK 48000000
#define FWS 1 // Flash wait states
@ -163,6 +165,7 @@ void EnableIO(void);
void DisableIO(void);
#endif
void hexdump(void *data, uint16_t size, uint16_t offset);
#define DEBUG_FUNC_IN()
#endif // HARDWARE_H

31
tos.c
View File

@ -102,28 +102,6 @@ static void mist_set_control(unsigned long ctrl) {
DisableFpga();
}
static void hexdump(void *data, unsigned long size, unsigned long offset) {
int i, b2c;
unsigned long n=0;
char *ptr = data;
if(!size) return;
while(size>0) {
iprintf("%08x: ", n + offset);
b2c = (size>16)?16:size;
for(i=0;i<b2c;i++) iprintf("%02x ", 0xff&ptr[i]);
iprintf(" ");
for(i=0;i<(16-b2c);i++) iprintf(" ");
for(i=0;i<b2c;i++) iprintf("%c", isprint(ptr[i])?ptr[i]:'.');
iprintf("\n");
ptr += b2c;
size -= b2c;
n += b2c;
}
}
static void mist_bus_request(char req) {
EnableFpga();
SPI(req?MIST_BUS_REQ:MIST_BUS_REL);
@ -295,6 +273,8 @@ static void handle_fdc(unsigned char *buffer) {
unsigned char fdc_data = buffer[7];
unsigned char drv_sel = 3-((buffer[8]>>2)&3);
unsigned char drv_side = 1-((buffer[8]>>1)&1);
// iprintf("FDC: sel %d, cmd %d\n", drv_sel, fdc_cmd);
// check if a matching disk image has been inserted
if(drv_sel && fdd_image[drv_sel-1].file.size) {
@ -306,12 +286,14 @@ static void handle_fdc(unsigned char *buffer) {
if((fdc_cmd & 0xc0) == 0x80) {
// convert track/sector/side into disk offset
unsigned int offset = drv_side;
unsigned int offset = drv_side;
offset += fdc_track * fdd_image[drv_sel-1].sides;
offset *= fdd_image[drv_sel-1].spt;
offset += fdc_sector-1;
while(scnt) {
// iprintf(" sector %d\n", offset);
DISKLED_ON;
FileSeek(&fdd_image[drv_sel-1].file, offset, SEEK_SET);
@ -338,6 +320,9 @@ static void handle_fdc(unsigned char *buffer) {
EnableFpga();
SPI(MIST_ACK_DMA);
DisableFpga();
// iprintf("done\n");
} else if((fdc_cmd & 0xc0) == 0xc0) {
char msg[32];

1
tos.h
View File

@ -70,6 +70,7 @@
#define TOS_CONTROL_STEREO 0x00400000
#define TOS_CONTROL_STE 0x00800000
#define TOS_CONTROL_MSTE 0x01000000
#define TOS_CONTROL_ETHERNET 0x02000000
unsigned long tos_system_ctrl(void);

View File

@ -3,57 +3,28 @@
//
// http://lxr.free-electrons.com/source/drivers/net/usb/asix.c?v=3.1
/*
Interface Descriptor:
bLength 9
bDescriptorType 4
bInterfaceNumber 0
bAlternateSetting 0
bNumEndpoints 3
bInterfaceClass 255 Vendor Specific Class
bInterfaceSubClass 255 Vendor Specific Subclass
bInterfaceProtocol 0
iInterface 7
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x81 EP 1 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0008 1x 8 bytes
bInterval 11
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x03 EP 3 OUT
bmAttributes 2
Transfer Type Bulk
Synch Type None
Usage Type Data
wMaxPacketSize 0x0200 1x 512 bytes
bInterval 0
*/
#include <stdio.h>
#include <string.h> // for memcpy
#include "debug.h"
#include "usb.h"
#include "asix.h"
#include "timer.h"
#include "mii.h"
#include "asix_const.h"
#include "max3421e.h"
#include "hardware.h"
#include "tos.h"
#define MAX_FRAMELEN 1536
static unsigned char rx_buf[MAX_FRAMELEN];
static uint16_t rx_cnt;
static unsigned char tx_buf[MAX_FRAMELEN];
static uint16_t tx_cnt, tx_offset;
static bool eth_present = 0;
// currently only AX88772 is supported as that's the only
// device i have
@ -70,132 +41,23 @@ static const struct {
{ 0, 0, 0 }
};
#define ETH_ALEN 6
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
#define AX_CMD_SET_SW_MII 0x06
#define AX_CMD_READ_MII_REG 0x07
#define AX_CMD_WRITE_MII_REG 0x08
#define AX_CMD_SET_HW_MII 0x0a
#define AX_CMD_READ_EEPROM 0x0b
#define AX_CMD_WRITE_EEPROM 0x0c
#define AX_CMD_WRITE_ENABLE 0x0d
#define AX_CMD_WRITE_DISABLE 0x0e
#define AX_CMD_READ_RX_CTL 0x0f
#define AX_CMD_WRITE_RX_CTL 0x10
#define AX_CMD_READ_IPG012 0x11
#define AX_CMD_WRITE_IPG0 0x12
#define AX_CMD_WRITE_IPG1 0x13
#define AX_CMD_READ_NODE_ID 0x13
#define AX_CMD_WRITE_IPG2 0x14
#define AX_CMD_WRITE_MULTI_FILTER 0x16
#define AX88172_CMD_READ_NODE_ID 0x17
#define AX_CMD_READ_PHY_ID 0x19
#define AX_CMD_READ_MEDIUM_STATUS 0x1a
#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
#define AX_CMD_READ_MONITOR_MODE 0x1c
#define AX_CMD_WRITE_MONITOR_MODE 0x1d
#define AX_CMD_READ_GPIOS 0x1e
#define AX_CMD_WRITE_GPIOS 0x1f
#define AX_CMD_SW_RESET 0x20
#define AX_CMD_SW_PHY_STATUS 0x21
#define AX_CMD_SW_PHY_SELECT 0x22
#define AX_SWRESET_CLEAR 0x00
#define AX_SWRESET_RR 0x01
#define AX_SWRESET_RT 0x02
#define AX_SWRESET_PRTE 0x04
#define AX_SWRESET_PRL 0x08
#define AX_SWRESET_BZ 0x10
#define AX_SWRESET_IPRL 0x20
#define AX_SWRESET_IPPD 0x40
/* AX88772 & AX88178 RX_CTL values */
#define AX_RX_CTL_SO 0x0080
#define AX_RX_CTL_AP 0x0020
#define AX_RX_CTL_AM 0x0010
#define AX_RX_CTL_AB 0x0008
#define AX_RX_CTL_SEP 0x0004
#define AX_RX_CTL_AMALL 0x0002
#define AX_RX_CTL_PRO 0x0001
#define AX_RX_CTL_MFB_2048 0x0000
#define AX_RX_CTL_MFB_4096 0x0100
#define AX_RX_CTL_MFB_8192 0x0200
#define AX_RX_CTL_MFB_16384 0x0300
#define AX88772_IPG0_DEFAULT 0x15
#define AX88772_IPG1_DEFAULT 0x0c
#define AX88772_IPG2_DEFAULT 0x12
/* AX88772 & AX88178 Medium Mode Register */
#define AX_MEDIUM_PF 0x0080
#define AX_MEDIUM_JFE 0x0040
#define AX_MEDIUM_TFC 0x0020
#define AX_MEDIUM_RFC 0x0010
#define AX_MEDIUM_ENCK 0x0008
#define AX_MEDIUM_AC 0x0004
#define AX_MEDIUM_FD 0x0002
#define AX_MEDIUM_GM 0x0001
#define AX_MEDIUM_SM 0x1000
#define AX_MEDIUM_SBP 0x0800
#define AX_MEDIUM_PS 0x0200
#define AX_MEDIUM_RE 0x0100
#define AX88178_MEDIUM_DEFAULT \
(AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
AX_MEDIUM_RE )
#define AX88772_MEDIUM_DEFAULT \
(AX_MEDIUM_FD | AX_MEDIUM_RFC | \
AX_MEDIUM_TFC | AX_MEDIUM_PS | \
AX_MEDIUM_AC | AX_MEDIUM_RE )
/* AX88772 & AX88178 RX_CTL values */
#define AX_RX_CTL_SO 0x0080
#define AX_RX_CTL_AP 0x0020
#define AX_RX_CTL_AM 0x0010
#define AX_RX_CTL_AB 0x0008
#define AX_RX_CTL_SEP 0x0004
#define AX_RX_CTL_AMALL 0x0002
#define AX_RX_CTL_PRO 0x0001
#define AX_RX_CTL_MFB_2048 0x0000
#define AX_RX_CTL_MFB_4096 0x0100
#define AX_RX_CTL_MFB_8192 0x0200
#define AX_RX_CTL_MFB_16384 0x0300
#define AX_DEFAULT_RX_CTL \
(AX_RX_CTL_SO | AX_RX_CTL_AB )
/* GPIO 0 .. 2 toggles */
#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */
#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */
#define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */
#define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */
#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */
#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */
#define AX_GPIO_RESERVED 0x40 /* Reserved */
#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */
#define ASIX_REQ_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
#define ASIX_REQ_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_VENDOR|USB_SETUP_RECIPIENT_DEVICE
static uint8_t asix_write_cmd(usb_device_t *dev, uint8_t cmd, uint16_t value, uint16_t index,
uint16_t size, uint8_t *data) {
asix_debugf("%s() cmd=0x%02x value=0x%04x index=0x%04x size=%d", __FUNCTION__,
cmd, value, index, size);
// asix_debugf("%s() cmd=0x%02x value=0x%04x index=0x%04x size=%d", __FUNCTION__,
// cmd, value, index, size);
return(usb_ctrl_req( dev, ASIX_REQ_OUT, cmd, index, value, 0, size, data));
return(usb_ctrl_req( dev, ASIX_REQ_OUT, cmd, value&0xff, value>>8, index, size, data));
}
static uint8_t asix_read_cmd(usb_device_t *dev, uint8_t cmd, uint16_t value, uint16_t index,
uint16_t size, void *data) {
uint8_t buf[size];
asix_debugf("asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
cmd, value, index, size);
// asix_debugf("asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d",
// cmd, value, index, size);
return(usb_ctrl_req( dev, ASIX_REQ_IN, cmd, index, value, 0, size, data));
return(usb_ctrl_req( dev, ASIX_REQ_IN, cmd, value&0xff, value>>8, index, size, data));
}
static uint8_t asix_write_gpio(usb_device_t *dev, uint16_t value, uint16_t sleep) {
@ -250,10 +112,7 @@ static inline uint8_t asix_set_hw_mii(usb_device_t *dev) {
}
static inline int8_t asix_get_phy_addr(usb_device_t *dev) {
union {
uint8_t b[2];
uint16_t w;
} buf;
uint8_t buf[2];
uint8_t ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, sizeof(buf), &buf);
@ -264,9 +123,9 @@ static inline int8_t asix_get_phy_addr(usb_device_t *dev) {
return ret;
}
asix_debugf("returning 0x%04x", buf.w);
asix_debugf("returning 0x%02x%02x", buf[1], buf[0]);
return buf.b[1];
return buf[1];
}
static uint16_t asix_mdio_read(usb_device_t *dev, uint8_t phy_id, uint8_t loc) {
@ -288,6 +147,7 @@ static void asix_mdio_write(usb_device_t *dev, uint8_t phy_id, uint8_t loc, uint
asix_set_hw_mii(dev);
}
#if 1
/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
static uint32_t asix_get_phyid(usb_device_t *dev) {
usb_asix_info_t *info = &(dev->asix_info);
@ -305,6 +165,36 @@ static uint32_t asix_get_phyid(usb_device_t *dev) {
phy_id |= (phy_reg & 0xffff);
return phy_id;
}
#else
/* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */
static uint32_t asix_get_phyid(usb_device_t *dev) {
usb_asix_info_t *info = &(dev->asix_info);
int16_t phy_reg;
uint32_t phy_id;
int i;
/* Poll for the rare case the FW or phy isn't ready yet. */
for (i = 0; i < 100; i++) {
phy_reg = asix_mdio_read(dev, info->phy_id, MII_PHYSID1);
if (phy_reg != 0 && phy_reg != 0xFFFF)
break;
timer_delay_msec(1);
}
if (phy_reg <= 0 || phy_reg == 0xFFFF)
return 0;
phy_id = (phy_reg & 0xffff) << 16;
phy_reg = asix_mdio_read(dev, info->phy_id, MII_PHYSID2);
if (phy_reg < 0)
return 0;
phy_id |= (phy_reg & 0xffff);
return phy_id;
}
#endif
static uint8_t asix_sw_reset(usb_device_t *dev, uint8_t flags) {
uint8_t rcode;
@ -312,6 +202,8 @@ static uint8_t asix_sw_reset(usb_device_t *dev, uint8_t flags) {
rcode = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
if (rcode != 0)
asix_debugf("Failed to send software reset: %02x", rcode);
else
timer_delay_msec(150);
return rcode;
}
@ -347,7 +239,6 @@ void mii_nway_restart(usb_device_t *dev) {
/* if autoneg is off, it's an error */
uint16_t bmcr = asix_mdio_read(dev, info->phy_id, MII_BMCR);
if(bmcr & BMCR_ANENABLE) {
bmcr |= BMCR_ANRESTART;
asix_mdio_write(dev, info->phy_id, MII_BMCR, bmcr);
@ -355,18 +246,112 @@ void mii_nway_restart(usb_device_t *dev) {
asix_debugf("%s() failed", __FUNCTION__);
}
static uint8_t asix_parse_conf(usb_device_t *dev, uint8_t conf, uint16_t len) {
usb_asix_info_t *info = &(dev->asix_info);
uint8_t rcode;
uint8_t epidx = 0;
union buf_u {
usb_configuration_descriptor_t conf_desc;
usb_interface_descriptor_t iface_desc;
usb_endpoint_descriptor_t ep_desc;
uint8_t raw[len];
} buf, *p;
if(rcode = usb_get_conf_descr(dev, len, conf, &buf.conf_desc))
return rcode;
/* scan through all descriptors */
p = &buf;
while(len > 0) {
switch(p->conf_desc.bDescriptorType) {
case USB_DESCRIPTOR_CONFIGURATION:
iprintf("conf descriptor size %d\n", p->conf_desc.bLength);
// we already had this, so we simply ignore it
break;
case USB_DESCRIPTOR_INTERFACE:
iprintf("iface descriptor size %d\n", p->iface_desc.bLength);
/* check the interface descriptors for supported class */
break;
case USB_DESCRIPTOR_ENDPOINT:
iprintf("endpoint descriptor size %d\n", p->ep_desc.bLength);
if(epidx < 3) {
// hexdump(p, p->conf_desc.bLength, 0);
// Handle interrupt endpoints
if ((p->ep_desc.bmAttributes & 0x03) == 3 &&
(p->ep_desc.bEndpointAddress & 0x80) == 0x80) {
asix_debugf("irq endpoint %d, interval = %dms",
p->ep_desc.bEndpointAddress & 0x0F, p->ep_desc.bInterval);
// Handling bInterval correctly is rather tricky. The meaning of
// this field differs between low speed/full speed vs. high speed.
// We are using a high speed device on a full speed link. Which
// rate is correct then? Furthermore this seems
// to be a common problem: http://www.lvr.com/usbfaq.htm
info->ep_int_idx = epidx;
info->int_poll_ms = p->ep_desc.bInterval;
}
if ((p->ep_desc.bmAttributes & 0x03) == 2 &&
(p->ep_desc.bEndpointAddress & 0x80) == 0x80) {
asix_debugf("bulk in endpoint %d", p->ep_desc.bEndpointAddress & 0x0F);
}
if ((p->ep_desc.bmAttributes & 0x03) == 2 &&
(p->ep_desc.bEndpointAddress & 0x80) == 0x00) {
asix_debugf("bulk out endpoint %d", p->ep_desc.bEndpointAddress & 0x0F);
}
// Fill in the endpoint info structure
info->ep[epidx].epAddr = (p->ep_desc.bEndpointAddress & 0x0F);
info->ep[epidx].maxPktSize = p->ep_desc.wMaxPacketSize[0];
info->ep[epidx].epAttribs = 0;
info->ep[epidx].bmNakPower = USB_NAK_NOWAIT;
epidx++;
}
break;
default:
iprintf("unsupported descriptor type %d size %d\n", p->raw[1], p->raw[0]);
}
// advance to next descriptor
len -= p->conf_desc.bLength;
p = (union buf_u*)(p->raw + p->conf_desc.bLength);
}
if(len != 0) {
iprintf("URGS, underrun: %d\n", len);
return USB_ERROR_CONFIGURAION_SIZE_MISMATCH;
}
return 0;
}
static uint8_t usb_asix_init(usb_device_t *dev) {
usb_asix_info_t *info = &(dev->asix_info);
uint8_t i, rcode = 0;
// only one ethernet dongle is supported at a time
if(eth_present)
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
// reset status
info->qNextPollTime = 0;
info->bPollEnable = false;
info->linkDetected = false;
info->ep.epAddr = 1;
info->ep.maxPktSize = 8;
info->ep.epAttribs = 0;
info->ep.bmNakPower = USB_NAK_NOWAIT;
for(i=0;i<3;i++) {
info->ep[i].epAddr = 1;
info->ep[i].maxPktSize = 8;
info->ep[i].epAttribs = 0;
info->ep[i].bmNakPower = USB_NAK_NOWAIT;
}
asix_debugf("%s(%d)", __FUNCTION__, dev->bAddress);
@ -399,15 +384,39 @@ static uint8_t usb_asix_init(usb_device_t *dev) {
return USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED;
}
asix_debugf("supported device");
// Set Configuration Value
iprintf("conf value = %d\n", buf.conf_desc.bConfigurationValue);
rcode = usb_set_conf(dev, buf.conf_desc.bConfigurationValue);
uint8_t num_of_conf = buf.dev_desc.bNumConfigurations;
iprintf("number of configurations: %d\n", num_of_conf);
if((rcode = asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) != 0) {
asix_debugf("setting gpio failed\n");
return rcode;
for(i=0; i<num_of_conf; i++) {
if(rcode = usb_get_conf_descr(dev, sizeof(usb_configuration_descriptor_t), i, &buf.conf_desc))
return rcode;
iprintf("conf descriptor %d has total size %d\n", i, buf.conf_desc.wTotalLength);
// extract number of interfaces
iprintf("number of interfaces: %d\n", buf.conf_desc.bNumInterfaces);
// parse directly if it already fitted completely into the buffer
if((rcode = asix_parse_conf(dev, i, buf.conf_desc.wTotalLength)) != 0) {
asix_debugf("parse conf failed");
return rcode;
}
}
asix_debugf("supported device");
if ((rcode = asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5)) < 0) {
asix_debugf("GPIO write failed");
return rcode;
}
/* 0x10 is the phy id of the embedded 10/100 ethernet phy */
int8_t embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
asix_debugf("embedded phy = %d", embd_phy);
if((rcode = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL)) != 0) {
asix_debugf("Select PHY #1 failed");
return rcode;
@ -418,28 +427,15 @@ static uint8_t usb_asix_init(usb_device_t *dev) {
return rcode;
}
timer_delay_msec(150);
if ((rcode = asix_sw_reset(dev, AX_SWRESET_CLEAR)) != 0) {
asix_debugf("reset(AX_SWRESET_CLEAR) failed");
return rcode;
}
timer_delay_msec(150);
if (embd_phy) {
if ((rcode = asix_sw_reset(dev, AX_SWRESET_IPRL)) != 0) {
asix_debugf("reset(AX_SWRESET_IPRL) failed");
return rcode;
}
} else {
if ((rcode = asix_sw_reset(dev, AX_SWRESET_PRTE)) != 0) {
asix_debugf("reset(AX_SWRESET_PRTE) failed");
return rcode;
}
if ((rcode = asix_sw_reset(dev, embd_phy?AX_SWRESET_IPRL:AX_SWRESET_PRTE)) != 0) {
asix_debugf("reset(AX_SWRESET_IPRL/PRTE) failed");
return rcode;
}
timer_delay_msec(150);
uint16_t rx_ctl = asix_read_rx_ctl(dev);
asix_debugf("RX_CTL is 0x%04x after software reset", rx_ctl);
@ -463,6 +459,9 @@ static uint8_t usb_asix_init(usb_device_t *dev) {
buf.eaddr[0], buf.eaddr[1], buf.eaddr[2],
buf.eaddr[3], buf.eaddr[4], buf.eaddr[5]);
// tell fpga about the mac address
user_io_eth_send_mac(buf.eaddr);
info->phy_id = asix_get_phy_addr(dev);
uint32_t phyid = asix_get_phyid(dev);
@ -473,15 +472,11 @@ static uint8_t usb_asix_init(usb_device_t *dev) {
return rcode;
}
timer_delay_msec(150);
if ((rcode = asix_sw_reset(dev, AX_SWRESET_IPRL | AX_SWRESET_PRL)) != 0) {
asix_debugf("reset(AX_SWRESET_IPRL | AX_SWRESET_PRL) failed");
return rcode;
}
timer_delay_msec(150);
asix_mdio_write(dev, info->phy_id, MII_BMCR, BMCR_RESET);
asix_mdio_write(dev, info->phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA);
@ -503,8 +498,6 @@ static uint8_t usb_asix_init(usb_device_t *dev) {
if ((rcode = asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL)) != 0)
return rcode;
iprintf("status = %x (%x)\n", asix_mdio_read(dev, info->phy_id, MII_BMSR), 12);
rx_ctl = asix_read_rx_ctl(dev);
iprintf("ASIX: RX_CTL is 0x%04x after all initializations\n", rx_ctl);
@ -513,41 +506,137 @@ static uint8_t usb_asix_init(usb_device_t *dev) {
info->bPollEnable = true;
rx_cnt = tx_cnt = 0; // reset buffers
// finally inform core about ethernet support
tos_update_sysctrl(tos_system_ctrl() | TOS_CONTROL_ETHERNET);
eth_present = 1;
return 0;
}
static uint8_t usb_asix_release(usb_device_t *dev) {
asix_debugf("%s()", __FUNCTION__);
// remove/disable ethernet support
tos_update_sysctrl(tos_system_ctrl() & (~TOS_CONTROL_ETHERNET));
eth_present = 0;
return 0;
}
void usb_asix_xmit(uint8_t *data, uint16_t len) {
asix_debugf("out %d", len);
if(!tx_cnt && (len <= MAX_FRAMELEN)) {
memcpy(tx_buf, data, len);
tx_cnt = len;
tx_offset = 0;
}
}
char testframe[] = {
0x3c, 0x00, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x12, 0x34, 0x80, 0x5d, 0x4c, 0x67,
0x08, 0x06, 0x00, 0x01, 0x08, 0x00, 0x06, 0x04, 0x00, 0x01, 0x00, 0x01, 0x80, 0x5d, 0x4c, 0x67,
0xc0, 0xa8, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xa8, 0x01, 0x64, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static uint8_t usb_asix_poll(usb_device_t *dev) {
usb_asix_info_t *info = &(dev->asix_info);
uint8_t rcode = 0;
if (!info->bPollEnable)
return 0;
if (info->qNextPollTime <= timer_get_msec()) {
uint16_t read = 1; // info->ep.maxPktSize;
uint8_t buf[info->ep.maxPktSize];
uint8_t rcode =
usb_in_transfer(dev, &(info->ep), &read, buf);
/* d = hrJERR */
// poll interrupt endpoint
if (info->qNextPollTime <= timer_get_msec()) {
// ------------ v TEST STUFF v --------------
{ static cnt = 20; if(!--cnt) {
iprintf("ETH status: %x\n", user_io_eth_get_status());
usb_asix_xmit(testframe, sizeof(testframe));
cnt = 20;
}}
// ------------ ^ TEST STUFF ^ --------------
uint16_t read = info->ep[info->ep_int_idx].maxPktSize;
uint8_t buf[info->ep[info->ep_int_idx].maxPktSize];
uint8_t rcode = usb_in_transfer(dev, &(info->ep[info->ep_int_idx]), &read, buf);
if (rcode) {
// if (rcode != hrNAK)
// iprintf("%s() error: %x\n", __FUNCTION__, rcode);
// else
// puts("nak");
if (rcode != hrNAK)
iprintf("%s() error: %x\n", __FUNCTION__, rcode);
} else {
iprintf("ASIX: %d bytes\n", read);
// iprintf("ASIX: int %d bytes\n", read);
// hexdump(buf, read, 0);
// primary or secondary link detected?
bool link_detected = ((buf[2] & 3) != 0);
if(link_detected != info->linkDetected) {
if(link_detected) {
iprintf("ASIX: Link detected\n");
} else
iprintf("ASIX: Link lost\n");
info->linkDetected = link_detected;
}
}
info->qNextPollTime = timer_get_msec() + 1000; // poll 1 times a second
// TODO: Do RX/TX handling at a much higher rate ...
// check if there's something to transmit
if(tx_cnt) {
uint16_t bytes2send = (tx_cnt-tx_offset > info->ep[2].maxPktSize)?
info->ep[2].maxPktSize:(tx_cnt-tx_offset);
// asix_debugf("bulk out %d of %d (ep %d), off %d", bytes2send, tx_cnt, info->ep[2].maxPktSize, tx_offset);
rcode = usb_out_transfer(dev, &(info->ep[2]), bytes2send, tx_buf + tx_offset);
// asix_debugf("%s() error: %x", __FUNCTION__, rcode);
tx_offset += bytes2send;
// mark buffer as free after last pkt was sent
if(bytes2send != info->ep[2].maxPktSize)
tx_cnt = 0;
}
// Try to read from bulk in endpoint (ep 2). Raw packets are received this way.
// The last USB packet being part of an ethernet frame is marked by being shorter
// than the USB FIFO size. If the last packet is exaclty if FIFO size, then an
// additional 0 byte packet is appended
{
uint16_t read = info->ep[1].maxPktSize;
// the rx buffer size (1536) is a multiple of the maxPktSize (64),
// so a transfer still fits into the buffer or it is already
// completely full. If it's full we drop all data. This will leave
// the buffered packet incomplete which isn't a problem since
// the packet was too long, anyway.
uint8_t *data = (rx_cnt <= MAX_FRAMELEN - info->ep[1].maxPktSize)?(rx_buf + rx_cnt):NULL;
rcode = usb_in_transfer(dev, &(info->ep[1]), &read, data);
if (rcode) {
if (rcode != hrNAK)
asix_debugf("%s() error: %x", __FUNCTION__, rcode);
} else {
rx_cnt += read;
if(read == info->ep[1].maxPktSize) {
} else {
asix_debugf("in %d", rx_cnt);
// hexdump(rx_buf, rx_cnt, 0);
rx_cnt = 0;
}
}
}
info->qNextPollTime = timer_get_msec() + info->int_poll_ms;
}
return rcode;

View File

@ -5,13 +5,17 @@
#include <inttypes.h>
typedef struct {
ep_t ep;
ep_t ep[3];
uint16_t phy_id;
uint32_t qNextPollTime; // next poll time
uint8_t ep_int_idx; // index of interrupt ep
uint8_t int_poll_ms; // poll interval in ms
bool bPollEnable;
bool linkDetected;
} usb_asix_info_t;
// interface to usb core
extern const usb_device_class_config_t usb_asix_class;
void usb_asix_xmit(uint8_t *data, uint16_t len);
#endif // ASIX_H

111
usb/asix_const.h Normal file
View File

@ -0,0 +1,111 @@
#ifndef ASIX_CONST_H
#define ASIX_CONST_H
#define ETH_ALEN 6
/* ASIX AX8817X based USB 2.0 Ethernet Devices */
#define AX_CMD_SET_SW_MII 0x06
#define AX_CMD_READ_MII_REG 0x07
#define AX_CMD_WRITE_MII_REG 0x08
#define AX_CMD_SET_HW_MII 0x0a
#define AX_CMD_READ_EEPROM 0x0b
#define AX_CMD_WRITE_EEPROM 0x0c
#define AX_CMD_WRITE_ENABLE 0x0d
#define AX_CMD_WRITE_DISABLE 0x0e
#define AX_CMD_READ_RX_CTL 0x0f
#define AX_CMD_WRITE_RX_CTL 0x10
#define AX_CMD_READ_IPG012 0x11
#define AX_CMD_WRITE_IPG0 0x12
#define AX_CMD_WRITE_IPG1 0x13
#define AX_CMD_READ_NODE_ID 0x13
#define AX_CMD_WRITE_IPG2 0x14
#define AX_CMD_WRITE_MULTI_FILTER 0x16
#define AX88172_CMD_READ_NODE_ID 0x17
#define AX_CMD_READ_PHY_ID 0x19
#define AX_CMD_READ_MEDIUM_STATUS 0x1a
#define AX_CMD_WRITE_MEDIUM_MODE 0x1b
#define AX_CMD_READ_MONITOR_MODE 0x1c
#define AX_CMD_WRITE_MONITOR_MODE 0x1d
#define AX_CMD_READ_GPIOS 0x1e
#define AX_CMD_WRITE_GPIOS 0x1f
#define AX_CMD_SW_RESET 0x20
#define AX_CMD_SW_PHY_STATUS 0x21
#define AX_CMD_SW_PHY_SELECT 0x22
#define AX_SWRESET_CLEAR 0x00
#define AX_SWRESET_RR 0x01
#define AX_SWRESET_RT 0x02
#define AX_SWRESET_PRTE 0x04
#define AX_SWRESET_PRL 0x08
#define AX_SWRESET_BZ 0x10
#define AX_SWRESET_IPRL 0x20
#define AX_SWRESET_IPPD 0x40
/* AX88772 & AX88178 RX_CTL values */
#define AX_RX_CTL_SO 0x0080
#define AX_RX_CTL_AP 0x0020
#define AX_RX_CTL_AM 0x0010
#define AX_RX_CTL_AB 0x0008
#define AX_RX_CTL_SEP 0x0004
#define AX_RX_CTL_AMALL 0x0002
#define AX_RX_CTL_PRO 0x0001
#define AX_RX_CTL_MFB_2048 0x0000
#define AX_RX_CTL_MFB_4096 0x0100
#define AX_RX_CTL_MFB_8192 0x0200
#define AX_RX_CTL_MFB_16384 0x0300
#define AX88772_IPG0_DEFAULT 0x15
#define AX88772_IPG1_DEFAULT 0x0c
#define AX88772_IPG2_DEFAULT 0x12
/* AX88772 & AX88178 Medium Mode Register */
#define AX_MEDIUM_PF 0x0080
#define AX_MEDIUM_JFE 0x0040
#define AX_MEDIUM_TFC 0x0020
#define AX_MEDIUM_RFC 0x0010
#define AX_MEDIUM_ENCK 0x0008
#define AX_MEDIUM_AC 0x0004
#define AX_MEDIUM_FD 0x0002
#define AX_MEDIUM_GM 0x0001
#define AX_MEDIUM_SM 0x1000
#define AX_MEDIUM_SBP 0x0800
#define AX_MEDIUM_PS 0x0200
#define AX_MEDIUM_RE 0x0100
#define AX88178_MEDIUM_DEFAULT \
(AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
AX_MEDIUM_RE )
#define AX88772_MEDIUM_DEFAULT \
(AX_MEDIUM_FD | AX_MEDIUM_RFC | \
AX_MEDIUM_TFC | AX_MEDIUM_PS | \
AX_MEDIUM_AC | AX_MEDIUM_RE )
/* AX88772 & AX88178 RX_CTL values */
#define AX_RX_CTL_SO 0x0080
#define AX_RX_CTL_AP 0x0020
#define AX_RX_CTL_AM 0x0010
#define AX_RX_CTL_AB 0x0008
#define AX_RX_CTL_SEP 0x0004
#define AX_RX_CTL_AMALL 0x0002
#define AX_RX_CTL_PRO 0x0001
#define AX_RX_CTL_MFB_2048 0x0000
#define AX_RX_CTL_MFB_4096 0x0100
#define AX_RX_CTL_MFB_8192 0x0200
#define AX_RX_CTL_MFB_16384 0x0300
#define AX_DEFAULT_RX_CTL \
(AX_RX_CTL_SO | AX_RX_CTL_AB )
/* GPIO 0 .. 2 toggles */
#define AX_GPIO_GPO0EN 0x01 /* GPIO0 Output enable */
#define AX_GPIO_GPO_0 0x02 /* GPIO0 Output value */
#define AX_GPIO_GPO1EN 0x04 /* GPIO1 Output enable */
#define AX_GPIO_GPO_1 0x08 /* GPIO1 Output value */
#define AX_GPIO_GPO2EN 0x10 /* GPIO2 Output enable */
#define AX_GPIO_GPO_2 0x20 /* GPIO2 Output value */
#define AX_GPIO_RESERVED 0x40 /* Reserved */
#define AX_GPIO_RSE 0x80 /* Reload serial EEPROM */
#endif //ASIX_CONST_H

101
usb/hid.c
View File

@ -5,6 +5,7 @@
#include "timer.h"
#include "hidparser.h"
#include "../user_io.h"
#include "../hardware.h"
// joystick todo:
// + renumber on unplug
@ -15,36 +16,6 @@
static unsigned char kbd_led_state = 0; // default: all leds off
static unsigned char joysticks = 0; // number of detected usb joysticks
static void hexdump(void *data, int size) {
int i,n = 0, b2c;
char *ptr = data;
if(!size) return;
while(size>0) {
iprintf("%04x: ", n);
b2c = (size>16)?16:size;
for(i=0;i<b2c;i++)
iprintf("%02x ", 0xff&ptr[i]);
iprintf(" ");
for(i=0;i<(16-b2c);i++)
iprintf(" ");
for(i=0;i<b2c;i++)
iprintf("%c", isprint(ptr[i])?ptr[i]:'.');
iprintf("\n");
ptr += b2c;
size -= b2c;
n += b2c;
}
}
uint8_t hid_get_joysticks(void) {
return joysticks;
}
@ -60,7 +31,7 @@ static uint8_t hid_get_report_descr(usb_device_t *dev, uint8_t iface, uint16_t s
if(!rcode) {
iprintf("HID report descriptor:\n");
hexdump(buf, size);
hexdump(buf, size, 0);
// we got a report descriptor. Try to parse it
if(parse_report_descriptor(buf, size)) {
@ -205,7 +176,7 @@ static uint8_t usb_hid_parse_conf(usb_device_t *dev, uint8_t conf, uint16_t len)
256 * p->hid_desc.wDescriptorLength[1];
iprintf(" -> report descriptor size = %d\n", len);
info->iface_info[info->bNumIfaces].report_size = len;
info->iface_info[info->bNumIfaces].report_desc_size = len;
}
}
break;
@ -289,9 +260,9 @@ static uint8_t usb_hid_init(usb_device_t *dev) {
// process all supported interfaces
for(i=0; i<info->bNumIfaces; i++) {
// no boot mode, try to parse HID report descriptor
if(!info->iface_info[info->bNumIfaces].has_boot_mode) {
if(!info->iface_info[i].has_boot_mode) {
rcode = hid_get_report_descr(dev,
info->iface_info[i].iface_idx, info->iface_info[i].report_size);
info->iface_info[i].iface_idx, info->iface_info[i].report_desc_size);
if (rcode)
return rcode;
}
@ -374,13 +345,9 @@ static uint8_t usb_hid_poll(usb_device_t *dev) {
if (rcode) {
if (rcode != hrNAK)
iprintf("%s() error: %d %d\n", __FUNCTION__, rcode, timer_get_msec());
// else
// puts("nak");
iprintf("%s() error: %d\n", __FUNCTION__, rcode);
} else {
// iprintf("interface %d: received %d bytes\n", i, read);
// successfully received some bytes
if(info->iface_info[i].has_boot_mode) {
if(info->iface_info[i].device_type == HID_DEVICE_MOUSE) {
@ -401,34 +368,38 @@ static uint8_t usb_hid_poll(usb_device_t *dev) {
if(info->iface_info[i].device_type == HID_DEVICE_JOYSTICK) {
hid_config_t *conf = &info->iface_info[i].conf;
uint8_t jmap = 0;
uint8_t ax;
if(read >= conf->report_size) {
uint8_t jmap = 0;
uint8_t ax;
iprintf("Joystick data:\n");
hexdump(buf, read);
// iprintf("Joystick data:\n");
// hexdump(buf, read, 0);
// currently only byte sized axes are allowed
ax = buf[conf->joystick.axis_byte_offset[0]];
if(ax < 64) jmap |= JOY_LEFT;
if(ax > 192) jmap |= JOY_RIGHT;
ax = buf[conf->joystick.axis_byte_offset[1]];
if(ax < 64) jmap |= JOY_UP;
if(ax > 192) jmap |= JOY_DOWN;
// ... and one button
if(buf[conf->joystick.button_byte_offset] & conf->joystick.button0_bitmask)
jmap |= JOY_BTN1;
// swap joystick 0 and 1 since 1 is the one used primarily on most systems
ax = info->iface_info[i].jindex;
if(ax == 0) ax = 1;
else if(ax == 1) ax = 0;
// check if joystick state has changed
if(jmap != info->iface_info[i].jmap) {
// and feed into joystick input system
user_io_joystick(ax, jmap);
info->iface_info[i].jmap = jmap;
// currently only byte sized axes are allowed
ax = buf[conf->joystick.axis_byte_offset[0]];
if(ax < 64) jmap |= JOY_LEFT;
if(ax > 192) jmap |= JOY_RIGHT;
ax = buf[conf->joystick.axis_byte_offset[1]];
if(ax < 64) jmap |= JOY_UP;
if(ax > 192) jmap |= JOY_DOWN;
// ... and one button
if(buf[conf->joystick.button_byte_offset] &
conf->joystick.button0_bitmask)
jmap |= JOY_BTN1;
// swap joystick 0 and 1 since 1 is the one
// used primarily on most systems
ax = info->iface_info[i].jindex;
if(ax == 0) ax = 1;
else if(ax == 1) ax = 0;
// check if joystick state has changed
if(jmap != info->iface_info[i].jmap) {
// and feed into joystick input system
user_io_joystick(ax, jmap);
info->iface_info[i].jmap = jmap;
}
}
}
}

View File

@ -45,7 +45,7 @@
typedef struct {
uint8_t iface_idx;
uint16_t report_size;
uint16_t report_desc_size;
uint8_t device_type;
bool has_boot_mode; // device supports boot mode

View File

@ -387,6 +387,8 @@ bool parse_report_descriptor(uint8_t *rep, uint16_t rep_size) {
hidp_debugf("total bit count: %d (%d bytes, %d bits)\n",
bit_count, bit_count/8, bit_count%8);
hid_conf[config_idx].report_size = bit_count/8;
// check if something useful was detected
if(hid_conf[config_idx].type == CONFIG_TYPE_JOYSTICK) {
if(setup_complete == JOYSTICK_COMPLETE) {

View File

@ -10,6 +10,7 @@
typedef struct {
uint8_t type: 2; // CONFIG_TYPE_...
uint8_t report_id;
uint8_t report_size;
union {
struct {

View File

@ -4,35 +4,6 @@
#include "timer.h"
#include "spi.h"
static void hexdump(void *data, int size) {
int i,n = 0, b2c;
char *ptr = data;
if(!size) return;
while(size>0) {
iprintf("%04x: ", n);
b2c = (size>16)?16:size;
for(i=0;i<b2c;i++)
iprintf("%02x ", 0xff&ptr[i]);
iprintf(" ");
for(i=0;i<(16-b2c);i++)
iprintf(" ");
for(i=0;i<b2c;i++)
iprintf("%c", isprint(ptr[i])?ptr[i]:'.');
iprintf("\n");
ptr += b2c;
size -= b2c;
n += b2c;
}
}
void max3421e_write_u08(uint8_t reg, uint8_t data) {
// iprintf("write %x %x\n", reg, data);
@ -51,7 +22,6 @@ uint8_t max3421e_read_u08(uint8_t reg) {
}
uint8_t *max3421e_write(uint8_t reg, uint8_t n, uint8_t* data) {
// hexdump(data, n);
spi_start(0);
spi_xmit(reg | MAX3421E_WRITE);
@ -61,10 +31,15 @@ uint8_t *max3421e_write(uint8_t reg, uint8_t n, uint8_t* data) {
return data;
}
// discard data if NULL ptr was provided
uint8_t *max3421e_read(uint8_t reg, uint8_t n, uint8_t* data) {
spi_start(0);
spi_xmit(reg);
while(n--) *data++ = spi_xmit(0);
if(data)
while(n--) *data++ = spi_xmit(0);
else
while(n--) spi_xmit(0);
spi_end();
return data;

View File

@ -21,6 +21,23 @@
#define BMCR_LOOPBACK 0x4000 /* TXD loopback bits */
#define BMCR_RESET 0x8000 /* Reset the DP83840 */
/* Basic mode status register. */
#define BMSR_ERCAP 0x0001 /* Ext-reg capability */
#define BMSR_JCD 0x0002 /* Jabber detected */
#define BMSR_LSTATUS 0x0004 /* Link status */
#define BMSR_ANEGCAPABLE 0x0008 /* Able to do auto-negotiation */
#define BMSR_RFAULT 0x0010 /* Remote fault detected */
#define BMSR_ANEGCOMPLETE 0x0020 /* Auto-negotiation complete */
#define BMSR_RESV 0x00c0 /* Unused... */
#define BMSR_ESTATEN 0x0100 /* Extended Status in R15 */
#define BMSR_100HALF2 0x0200 /* Can do 100BASE-T2 HDX */
#define BMSR_100FULL2 0x0400 /* Can do 100BASE-T2 FDX */
#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */
#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */
#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */
#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */
#define BMSR_100BASE4 0x8000 /* Can do 100mbps, 4k packets */
/* Advertisement control register. */
#define ADVERTISE_SLCT 0x001f /* Selector bits */
#define ADVERTISE_CSMA 0x0001 /* Only selector supported */

View File

@ -186,15 +186,14 @@ uint8_t usb_in_transfer( usb_device_t *dev, ep_t *ep, uint16_t *nbytesptr, uint8
uint16_t nak_limit = 0;
uint8_t rcode = usb_set_address(dev, ep, &nak_limit);
if (rcode)
return rcode;
if (rcode) return rcode;
return usb_InTransfer(ep, nak_limit, nbytesptr, data);
}
uint8_t usb_OutTransfer(ep_t *pep, uint16_t nak_limit,
uint16_t nbytes, uint8_t *data) {
iprintf("%s(%d)\n", __FUNCTION__, nbytes);
// iprintf("%s(%d)\n", __FUNCTION__, nbytes);
uint8_t rcode = 0, retry_count;
uint16_t bytes_tosend, nak_count;
@ -268,6 +267,18 @@ uint8_t usb_OutTransfer(ep_t *pep, uint16_t nak_limit,
return( rcode ); //should be 0 in all cases
}
/* OUT transfer to arbitrary endpoint. Handles multiple packets if necessary. Transfers 'nbytes' bytes. */
/* Handles NAK bug per Maxim Application Note 4000 for single buffer transfer */
/* rcode 0 if no errors. rcode 01-0f is relayed from HRSL */
uint8_t usb_out_transfer(usb_device_t *dev, ep_t *ep, uint16_t nbytes, uint8_t* data ) {
uint16_t nak_limit = 0;
uint8_t rcode = usb_set_address(dev, ep, &nak_limit);
if (rcode) return rcode;
return usb_OutTransfer(ep, nak_limit, nbytes, data);
}
/* Control transfer. Sets address, endpoint, fills control packet */
/* with necessary data, dispatches control packet, and initiates */
/* bulk IN transfer, depending on request. Actual requests are defined */
@ -279,8 +290,8 @@ uint8_t usb_OutTransfer(ep_t *pep, uint16_t nak_limit,
uint8_t usb_ctrl_req(usb_device_t *dev, uint8_t bmReqType,
uint8_t bRequest, uint8_t wValLo, uint8_t wValHi,
uint16_t wInd, uint16_t nbytes, uint8_t* dataptr) {
iprintf("%s(addr=%x, len=%d, ptr=%p)\n", __FUNCTION__,
dev->bAddress, nbytes, dataptr);
// iprintf("%s(addr=%x, len=%d, ptr=%p)\n", __FUNCTION__,
// dev->bAddress, nbytes, dataptr);
bool direction = false; //request direction, IN or OUT
uint8_t rcode;
setup_pkt_t setup_pkt;

View File

@ -243,6 +243,7 @@ uint8_t usb_get_dev_descr( usb_device_t *, uint16_t nbytes, usb_device_descripto
uint8_t usb_get_conf_descr( usb_device_t *, uint16_t nbytes, uint8_t conf, usb_configuration_descriptor_t* dataptr );
uint8_t usb_set_conf( usb_device_t *dev, uint8_t conf_value );
uint8_t usb_in_transfer( usb_device_t *, ep_t *ep, uint16_t *nbytesptr, uint8_t* data);
uint8_t usb_out_transfer( usb_device_t *, ep_t *ep, uint16_t nbytes, uint8_t* data );
uint8_t usb_release_device(uint8_t parent, uint8_t port);
usb_device_t *usb_get_devices();

View File

@ -155,10 +155,10 @@ void user_io_joystick(unsigned char joystick, unsigned char map) {
}
// transmit serial/rs232 data into core
void user_io_serial_tx(char chr) {
void user_io_serial_tx(char *chr, uint16_t cnt) {
EnableIO();
SPI(UIO_SERIAL_OUT);
SPI(chr);
while(cnt--) SPI(*chr++);
DisableIO();
}
@ -169,7 +169,48 @@ void user_io_midi_tx(char chr) {
SPI(chr);
DisableIO();
}
// send ethernet mac address into FPGA
void user_io_eth_send_mac(uint8_t *mac) {
uint8_t i;
EnableIO();
SPI(UIO_ETH_MAC);
for(i=0;i<6;i++) SPI(*mac++);
DisableIO();
}
// read 32 bit ethernet status word from FPGA
uint32_t user_io_eth_get_status(void) {
uint32_t s;
EnableIO();
SPI(UIO_ETH_STATUS);
s = SPI(0);
s = (s<<8) | SPI(0);
s = (s<<8) | SPI(0);
s = (s<<8) | SPI(0);
DisableIO();
return s;
}
// read ethernet frame from FPGAs ethernet tx buffer
void user_io_eth_receive_tx_frame(uint8_t *d, uint16_t len) {
EnableIO();
SPI(UIO_ETH_FRM_IN);
while(len--) *d++=SPI(0);
DisableIO();
}
// write ethernet frame to FPGAs rx buffer
void user_io_eth_send_rx_frame(uint8_t *s, uint16_t len) {
EnableIO();
SPI(UIO_ETH_FRM_OUT);
while(len--) SPI(*s++);
DisableIO();
}
void user_io_poll() {
if((core_type != CORE_TYPE_MINIMIG) &&
(core_type != CORE_TYPE_PACE) &&

View File

@ -6,6 +6,8 @@
#ifndef USER_IO_H
#define USER_IO_H
#include <inttypes.h>
#define UIO_STATUS 0x00
#define UIO_BUT_SW 0x01
@ -17,6 +19,7 @@
#define UIO_KBD_OSD 0x06 // keycodes used by OSD only
// codes as used by MiST (atari)
// directions (in/out) are from an io controller view
#define UIO_IKBD_OUT 0x02
#define UIO_IKBD_IN 0x03
#define UIO_SERIAL_OUT 0x04
@ -24,6 +27,10 @@
#define UIO_PARALLEL_IN 0x06
#define UIO_MIDI_OUT 0x07
#define UIO_MIDI_IN 0x08
#define UIO_ETH_MAC 0x09
#define UIO_ETH_STATUS 0x0a
#define UIO_ETH_FRM_IN 0x0b
#define UIO_ETH_FRM_OUT 0x0c
// codes as used by 8bit (atari 800)
#define UIO_GET_STATUS 0x50
@ -59,7 +66,14 @@ char user_io_menu_button();
char user_io_button_dip_switch1();
char user_io_user_button();
void user_io_osd_key_enable(char);
void user_io_serial_tx(char);
void user_io_serial_tx(char *, uint16_t);
// io controllers interface for FPGA ethernet emulation using usb ethernet
// devices attached to the io controller (ethernec emulation)
void user_io_eth_send_mac(uint8_t *);
uint32_t user_io_eth_get_status(void);
void user_io_eth_send_rx_frame(uint8_t *, uint16_t);
void user_io_eth_receive_tx_frame(uint8_t *, uint16_t);
// hooks from the usb layer
void user_io_mouse(unsigned char b, char x, char y);