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:
parent
57d45c91de
commit
73e7f4cad4
112
cdc_control.c
112
cdc_control.c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
2
debug.h
2
debug.h
@ -2,6 +2,8 @@
|
||||
#ifndef DEBUG_H
|
||||
#define DEBUG_H
|
||||
|
||||
#include "hardware.h"
|
||||
|
||||
// ------------ usb debugging -----------
|
||||
|
||||
#if 1
|
||||
|
||||
29
hardware.c
29
hardware.c
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
31
tos.c
@ -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
1
tos.h
@ -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);
|
||||
|
||||
|
||||
507
usb/asix.c
507
usb/asix.c
@ -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;
|
||||
|
||||
@ -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
111
usb/asix_const.h
Normal 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
101
usb/hid.c
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
typedef struct {
|
||||
uint8_t type: 2; // CONFIG_TYPE_...
|
||||
uint8_t report_id;
|
||||
uint8_t report_size;
|
||||
|
||||
union {
|
||||
struct {
|
||||
|
||||
@ -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;
|
||||
|
||||
17
usb/mii.h
17
usb/mii.h
@ -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 */
|
||||
|
||||
21
usb/usb.c
21
usb/usb.c
@ -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;
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
47
user_io.c
47
user_io.c
@ -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) &&
|
||||
|
||||
16
user_io.h
16
user_io.h
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user