URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/orpsocv2/sw
- from Rev 528 to Rev 530
- ↔ Reverse comparison
Rev 528 → Rev 530
/tests/ethmac/board/ethmac-ping.c
45,6 → 45,7
#include "printf.h" |
#include "eth-phy-mii.h" |
|
|
volatile unsigned tx_done; |
static int next_tx_buf_num; |
|
63,6 → 64,10
//#define OUR_IP_BYTES 0xac,0x1e,0x0,0x2 // 172.30.0.2 |
//#define OUR_IP_LONG 0xac1e0002 |
|
//#define OUR_IP_BYTES 0xa,0x0,0x0,0x14 // 10.0.0.20 |
//#define OUR_IP_LONG 0x0a000014 |
|
|
static char our_ip[4] = {OUR_IP_BYTES}; |
|
#define DEST_IP_BYTES 0xc0,0xa8,0x64,0x69 // 192 .168.100.105 |
69,10 → 74,12
//#define DEST_IP_BYTES 0xc0,0xa8,0x01,0x08 // 192 .168.1.8 |
//#define DEST_IP_BYTES 0xc0,0xa8,0x00,0x0f // 192 .168.0.15 |
//#define DEST_IP_BYTES 0xac,0x1e,0x0,0x01 // 172.30.0.1 |
//#define DEST_IP_BYTES 0xa,0x0,0x0,0x1 // 10.0.0.1 |
|
#define BCAST_DEST_IP_BYTES 0xc0,0xa8,0x64,0xff // 192.168.100.255 |
//#define BCAST_DEST_IP_BYTES 0xc0,0xa8,0x01,0xff // 192.168.1.255 |
//#define BCAST_DEST_IP_BYTES 0xc0,0xa8,0x00,0xff // 192.168.0.255 |
//#define BCAST_DEST_IP_BYTES 0xa,0x0,0x0,0xff // 10.0.0.255 |
|
/* Functions in this file */ |
void ethmac_setup(void); |
88,6 → 95,8
|
// Global used to control whether we print out packets as we receive them |
int print_packet_contents; |
int packet_inspect_debug; |
int print_ethmac_debug_reg; |
|
/* Let the ethernet packets use a space beginning here for buffering */ |
#define ETH_BUFF_BASE 0x01000000 |
104,8 → 113,8
|
/* Buffer number (must be 2^n) |
*/ |
#define OETH_RXBD_NUM 64 |
#define OETH_TXBD_NUM 64 |
#define OETH_RXBD_NUM 124 |
#define OETH_TXBD_NUM 4 |
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1) |
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1) |
|
137,6 → 146,82
// struct net_device_stats stats; |
}; |
|
#define PRINT_BIT_NAME(bit,name) printf("%02d:"name" %d\n",bit,!!(reg&(1<<bit))) |
void oeth_print_moder(unsigned long reg) |
{ |
PRINT_BIT_NAME(16,"RECSMALL"); |
PRINT_BIT_NAME(15,"PAD"); |
PRINT_BIT_NAME(14,"HUGEN"); |
PRINT_BIT_NAME(13,"CRCEN"); |
PRINT_BIT_NAME(12,"DLYCRCEN"); |
PRINT_BIT_NAME(10,"FULLD"); |
PRINT_BIT_NAME(9,"EXDFREN"); |
PRINT_BIT_NAME(8,"NOBCKOF"); |
PRINT_BIT_NAME(7,"LOOPBCK"); |
PRINT_BIT_NAME(6,"IFG"); |
PRINT_BIT_NAME(5,"PRO"); |
PRINT_BIT_NAME(4,"IAM"); |
PRINT_BIT_NAME(3,"BRO"); |
PRINT_BIT_NAME(2,"NOPRE"); |
PRINT_BIT_NAME(1,"TXEN"); |
PRINT_BIT_NAME(0,"RXEN"); |
} |
|
void oeth_print_intsource(unsigned long reg) |
{ |
PRINT_BIT_NAME(6,"RXCtrlFrame"); |
PRINT_BIT_NAME(5,"TXCtrlFrame"); |
PRINT_BIT_NAME(4,"BUSY"); |
PRINT_BIT_NAME(3,"RXE"); |
PRINT_BIT_NAME(2,"RXB"); |
PRINT_BIT_NAME(1,"TXE"); |
PRINT_BIT_NAME(0,"TXB"); |
} |
|
void oeth_print_ctrlmoder(unsigned long reg) |
{ |
PRINT_BIT_NAME(2,"TXFLOW"); |
PRINT_BIT_NAME(1,"RXFLOW"); |
PRINT_BIT_NAME(0,"PASSALL"); |
} |
|
void oeth_print_txbuf(unsigned long reg) |
{ |
printf("RD%d ",!!(reg&(1<<15))); |
printf("IQ%d ",!!(reg&(1<<14))); |
printf("WP%d ",!!(reg&(1<<13))); |
printf("PD%d ",!!(reg&(1<<12))); |
printf("CC%d ",!!(reg&(1<<11))); |
printf("UN%d ",!!(reg&(1<<8))); |
printf("RY%d ",!!(reg&(1<<3))); |
printf("LC%d ",!!(reg&(1<<2))); |
printf("DF%d ",!!(reg&(1<<1))); |
printf("CS%d ",!!(reg&(1<<0))); |
printf("\n"); |
|
} |
|
|
void oeth_print_rxbuf(unsigned long reg) |
{ |
printf("EM%d ",!!(reg&(1<<15))); |
printf("IQ%d ",!!(reg&(1<<14))); |
printf("WP%d ",!!(reg&(1<<13))); |
printf("PD%d ",!!(reg&(1<<12))); |
printf("CF%d ",!!(reg&(1<<8))); |
//printf("MS%d ",!!(reg&(1<<7))); |
printf("OR%d ",!!(reg&(1<<6))); |
printf("IS%d ",!!(reg&(1<<5))); |
printf("DN%d ",!!(reg&(1<<4))); |
printf("TL%d ",!!(reg&(1<<3))); |
printf("SF%d ",!!(reg&(1<<2))); |
printf("CE%d ",!!(reg&(1<<1))); |
printf("LC%d ",!!(reg&(1<<0))); |
printf("\n"); |
|
} |
|
// PRINT_BIT_NAME(,""); |
void oeth_printregs(void) |
{ |
volatile oeth_regs *regs; |
144,8 → 229,10
|
printf("Oeth regs: Mode Register : 0x%lx\n", |
(unsigned long) regs->moder); /* Mode Register */ |
oeth_print_moder((unsigned long) regs->moder); |
printf("Oeth regs: Interrupt Source Register 0x%lx\n", |
(unsigned long) regs->int_src); /* Interrupt Source Register */ |
oeth_print_intsource((unsigned long) regs->int_src); |
printf("Oeth regs: Interrupt Mask Register 0x%lx\n", |
(unsigned long) regs->int_mask); /* Interrupt Mask Register */ |
printf("Oeth regs: Back to Bak Inter Packet Gap Register 0x%lx\n", |
162,6 → 249,7
(unsigned long) regs->tx_bd_num); /* Transmit Buffer Descriptor Number Register */ |
printf("Oeth regs: Control Module Mode Register 0x%lx\n", |
(unsigned long) regs->ctrlmoder); /* Control Module Mode Register */ |
oeth_print_ctrlmoder((unsigned long) regs->ctrlmoder); |
printf("Oeth regs: MII Mode Register 0x%lx\n", |
(unsigned long) regs->miimoder); /* MII Mode Register */ |
printf("Oeth regs: MII Command Register 0x%lx\n", |
182,9 → 270,23
(unsigned long) regs->hash_addr0); /* Hash Register 0 */ |
printf("Oeth regs: Hash Register 1 0x%lx\n", |
(unsigned long) regs->hash_addr1); /* Hash Register 1 */ |
printf("Oeth regs: TXCTRL 0x%lx\n", |
(unsigned long) regs->txctrl); /* TX ctrl reg */ |
printf("Oeth regs: RXCTRL 0x%lx\n", |
(unsigned long) regs->rxctrl); /* RX ctrl reg */ |
printf("Oeth regs: WBDBG 0x%lx\n", |
(unsigned long) regs->wbdbg); /* Wishbone debug reg */ |
|
} |
|
void oeth_print_wbdebug(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
printf("Oeth regs: WBDBG 0x%lx\n", |
(unsigned long) regs->wbdbg); /* Wishbone debug reg */ |
} |
|
static int last_char; |
|
void spin_cursor(void) |
909,7 → 1011,61
return; |
} |
|
void oeth_ctrlmode_switch(void) |
{ |
volatile oeth_regs *regs; |
|
regs = (oeth_regs *)(OETH_REG_BASE); |
|
if (regs->ctrlmoder & (OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW)) |
{ |
printf("Disabling TX/RX flow control"); |
|
regs->ctrlmoder = 0; |
} |
else |
{ |
printf("Enabling TX/RX flow control"); |
|
regs->ctrlmoder = (OETH_CTRLMODER_TXFLOW | |
OETH_CTRLMODER_RXFLOW); |
|
} |
|
} |
|
void |
oeth_toggle_promiscuous(void) |
{ |
// from arch/or32/drivers/open_eth.c |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
if ( regs->moder & OETH_MODER_PRO ) |
{ |
printf("Disabling "); |
regs->moder &= ~OETH_MODER_PRO; |
|
} |
else |
{ |
printf("Enabling "); |
regs->moder |= OETH_MODER_PRO; |
|
} |
printf("promisucous mode\n"); |
} |
|
void oeth_transmit_pause(void) |
{ |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
regs->txctrl = 0x1fffe; |
} |
|
|
void |
ethmac_togglehugen(void) |
{ |
|
982,7 → 1138,7
|
/* print packet contents */ |
static void |
oeth_print_packet(unsigned long add, int len) |
oeth_print_packet(int bd, unsigned long add, int len) |
{ |
|
int truncate = (len > 256); |
989,7 → 1145,7
int length_to_print = truncate ? 256 : len; |
|
int i; |
printf("\nipacket: add = %lx len = %d\n", add, len); |
printf("\nbd%03d packet: add = %lx len = %d\n", bd,add, len); |
for(i = 0; i < length_to_print; i++) { |
if(!(i % 8)) |
printf(" "); |
1062,7 → 1218,13
*/ |
tx_bd->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_CRC | OETH_TX_BD_IRQ); |
|
next_tx_buf_num = (next_tx_buf_num + 1) & OETH_TXBD_NUM_MASK; |
//next_tx_buf_num = (next_tx_buf_num + 1) & OETH_TXBD_NUM_MASK; |
next_tx_buf_num++; |
if (next_tx_buf_num == OETH_TXBD_NUM) |
{ |
next_tx_buf_num = 0; |
} |
|
|
return; |
|
1090,7 → 1252,7
{ |
// Something in this buffer! |
printf("Oeth: RX in buf %d - len_status: 0x%lx\n",i, rx_bd[i].len_status); |
oeth_print_packet(rx_bd[i].addr, rx_bd[i].len_status >> 16); |
oeth_print_packet(i,rx_bd[i].addr, rx_bd[i].len_status >> 16); |
/* Clear recieved bit */ |
rx_bd[i].len_status |= OETH_RX_BD_EMPTY; |
printf("\t end of packet\n\n"); |
1098,23 → 1260,36
} |
} |
|
#include "spr-defs.h" |
|
/* Print out all buffer descriptors */ |
void oeth_dump_bds() |
{ |
unsigned long* bd_base = (unsigned long*) OETH_BD_BASE; |
// Disable interrupts |
mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_IEE); |
|
int i; |
for(i=0;i<OETH_TXBD_NUM;i++) |
{ |
printf("oeth: tx_bd%d: len_status: %lx ",i,*bd_base++); |
printf("addr: %lx\n", *bd_base++); |
} |
unsigned long* bd_base = (unsigned long*) OETH_BD_BASE; |
|
for(i=0;i<OETH_RXBD_NUM;i++) |
{ |
printf("oeth: rx_bd%d: len_status: %lx ",i,*bd_base++); |
printf("addr: %lx\n", *bd_base++); |
} |
int i; |
for(i=0;i<OETH_TXBD_NUM;i++) |
{ |
printf("TXBD%03d len_status %08lx ",i,*bd_base); |
oeth_print_txbuf(*bd_base++); |
//printf("addr: %lx\n", *bd_base++); |
*bd_base++; |
} |
|
for(i=0;i<OETH_RXBD_NUM;i++) |
{ |
printf("RXBD%03d len_status %08lx ",i,*bd_base); |
oeth_print_rxbuf(*bd_base++); |
*bd_base++; |
|
//printf("addr: %lx\n", *bd_base++); |
} |
|
// Enable interrupts |
mtspr (SPR_SR, mfspr (SPR_SR) | SPR_SR_IEE); |
|
} |
|
1318,70 → 1493,89
oeth_interrupt(void) |
{ |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
uint int_events; |
int serviced; |
uint int_events; |
int serviced; |
|
serviced = 0; |
serviced = 0; |
|
/* Get the interrupt events that caused us to be here. |
*/ |
int_events = regs->int_src; |
regs->int_src = int_events; |
/* Get the interrupt events that caused us to be here. |
*/ |
int_events = regs->int_src; |
regs->int_src = int_events; |
|
|
/* Indicate busy */ |
if (int_events & OETH_INT_BUSY) |
{ |
printf("\tBusy flag\n"); |
/* |
printf("\n=tx_ | %x | %x | %x | %x | %x | %x | %x | %x\n", |
((oeth_bd *)(OETH_BD_BASE))->len_status, |
((oeth_bd *)(OETH_BD_BASE+8))->len_status, |
((oeth_bd *)(OETH_BD_BASE+16))->len_status, |
((oeth_bd *)(OETH_BD_BASE+24))->len_status, |
((oeth_bd *)(OETH_BD_BASE+32))->len_status, |
((oeth_bd *)(OETH_BD_BASE+40))->len_status, |
((oeth_bd *)(OETH_BD_BASE+48))->len_status, |
((oeth_bd *)(OETH_BD_BASE+56))->len_status); |
*/ |
printf("=rx_ | %x | %x | %x | %x | %x | %x | %x | %x\n", |
((oeth_bd *)(OETH_BD_BASE+64))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+8))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+16))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+24))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+32))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+40))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+48))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+56))->len_status); |
/* Indicate busy */ |
if (int_events & OETH_INT_BUSY) |
{ |
printf("\tBusy flag\n"); |
/* |
printf("\n=tx_ | %x | %x | %x | %x | %x | %x | %x | %x\n", |
((oeth_bd *)(OETH_BD_BASE))->len_status, |
((oeth_bd *)(OETH_BD_BASE+8))->len_status, |
((oeth_bd *)(OETH_BD_BASE+16))->len_status, |
((oeth_bd *)(OETH_BD_BASE+24))->len_status, |
((oeth_bd *)(OETH_BD_BASE+32))->len_status, |
((oeth_bd *)(OETH_BD_BASE+40))->len_status, |
((oeth_bd *)(OETH_BD_BASE+48))->len_status, |
((oeth_bd *)(OETH_BD_BASE+56))->len_status); |
*/ |
printf("=rx_ | %x | %x | %x | %x | %x | %x | %x | %x\n", |
((oeth_bd *)(OETH_BD_BASE+64))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+8))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+16))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+24))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+32))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+40))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+48))->len_status, |
((oeth_bd *)(OETH_BD_BASE+64+56))->len_status); |
|
printf("=int | txb %d | txe %d | rxb %d | rxe %d | busy %d\n", |
(int_events & OETH_INT_TXB) > 0, |
(int_events & OETH_INT_TXE) > 0, |
(int_events & OETH_INT_RXF) > 0, |
(int_events & OETH_INT_RXE) > 0, |
(int_events & OETH_INT_BUSY) > 0); |
} |
|
/* Handle receive event in its own function. |
*/ |
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) { |
serviced |= 0x1; |
oeth_rx(); |
} |
printf("=int | rxc %d | txc %d | txb %d | txe %d | rxb %d | rxe %d | busy %d\n", |
(int_events & OETH_INT_RXC) > 0, |
(int_events & OETH_INT_TXC) > 0, |
(int_events & OETH_INT_TXB) > 0, |
(int_events & OETH_INT_TXE) > 0, |
(int_events & OETH_INT_RXF) > 0, |
(int_events & OETH_INT_RXE) > 0, |
(int_events & OETH_INT_BUSY) > 0); |
}/* |
else |
printf("=int | rxc %d | txc %d | txb %d | txe %d | rxb %d | rxe %d | busy %d\n", |
(int_events & OETH_INT_RXC) > 0, |
(int_events & OETH_INT_TXC) > 0, |
(int_events & OETH_INT_TXB) > 0, |
(int_events & OETH_INT_TXE) > 0, |
(int_events & OETH_INT_RXF) > 0, |
(int_events & OETH_INT_RXE) > 0, |
(int_events & OETH_INT_BUSY) > 0); |
*/ |
/* Handle receive event in its own function. |
*/ |
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) { |
serviced |= 0x1; |
if (print_ethmac_debug_reg) |
oeth_print_wbdebug(); |
oeth_rx(); |
if (print_ethmac_debug_reg) |
oeth_print_wbdebug(); |
} |
|
/* Handle transmit event in its own function. |
*/ |
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) { |
serviced |= 0x2; |
oeth_tx(); |
serviced |= 0x2; |
/* Handle transmit event in its own function. |
*/ |
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) { |
if (print_ethmac_debug_reg) |
oeth_print_wbdebug(); |
serviced |= 0x2; |
oeth_tx(); |
serviced |= 0x2; |
if (print_ethmac_debug_reg) |
oeth_print_wbdebug(); |
|
} |
} |
|
return; |
return; |
} |
|
// ARP stuff |
1552,6 → 1746,10
// Check for ICMP echo request type |
if (!(icmp->type == ICMP_TYPE_ECHO_REQ)) |
return; |
|
// Skip forward to the target I.P address |
if (packet_inspect_debug) |
printf("Ping packet\n"); |
|
// Go ahead and construct a response packet |
// Setup pointers |
1701,11 → 1899,15
|
if (arp->ar_hrd == ARP_ETHER && arp->ar_op == ARPOP_REQUEST) |
{ |
// Skip forward to the target I.P address |
// Skip forward to the target I.P address |
if (packet_inspect_debug) |
printf("ARP packet\n"); |
|
char * internet_protocol_adr = (((unsigned long)&arp->ar_data[0]) + (arp->ar_hln * 2) + (arp->ar_pln)); |
char * internet_protocol_adr = (((unsigned long)&arp->ar_data[0]) + |
(arp->ar_hln * 2) + (arp->ar_pln)); |
|
//printf("Is ARP ethernet request\ncheck adr at 0x%.8x\n",internet_protocol_adr); |
//printf("Is ARP ethernet request\ncheck adr at 0x%.8x\n", |
// internet_protocol_adr); |
if ((internet_protocol_adr[0] == our_ip[0]) && |
(internet_protocol_adr[1] == our_ip[1]) && |
(internet_protocol_adr[2] == our_ip[2]) && |
1731,15 → 1933,18
reply_arp->ar_pln = 0x04; |
reply_arp->ar_op = ARPOP_REPLY; |
// My MAC |
memcpy( (void*)&reply_arp->ar_data[0] , (void*)&reply_pkt->et_src , 6); |
memcpy( (void*)&reply_arp->ar_data[0] , |
(void*)&reply_pkt->et_src , 6); |
// My IP |
memcpy( (void*)&reply_arp->ar_data[6] , (void*)&our_ip , 4); |
// Their MAC |
memcpy( (void*)&reply_arp->ar_data[10] , (void*)ð_pkt->et_src , 6); |
memcpy( (void*)&reply_arp->ar_data[10] , |
(void*)ð_pkt->et_src , 6); |
// Their IP |
char * their_internet_protocol_adr = |
(((unsigned long)&arp->ar_data[0]) + arp->ar_hln ); |
memcpy( (void*)&reply_arp->ar_data[16] , (void*)&their_internet_protocol_adr[0] , 4); |
memcpy( (void*)&reply_arp->ar_data[16] , |
(void*)&their_internet_protocol_adr[0] , 4); |
|
tx_packet((void*)arp_reply_packet,(ETHER_HDR_SIZE+ARP_HDR_SIZE) ); |
|
1753,74 → 1958,84
static void |
oeth_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *rx_bdp; |
int pkt_len, i; |
int bad = 0; |
volatile oeth_bd *rx_bdp; |
int pkt_len, i; |
int bad = 0; |
|
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
if (print_packet_contents) |
printf("rx"); |
if (print_packet_contents) |
printf("rx "); |
|
/* Find RX buffers marked as having received data */ |
for(i = 0; i < OETH_RXBD_NUM; i++) |
{ |
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ /* Looking for NOT empty buffers desc. */ |
/* Check status for errors. |
*/ |
if (rx_bdp[i].len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) { |
bad = 1; |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) { |
bad = 1; |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) { |
bad = 1; |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) { |
bad = 1; |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) { |
/* Find RX buffers marked as having received data */ |
for(i = 0; i < OETH_RXBD_NUM; i++) |
{ |
/* Looking for NOT empty buffers desc. */ |
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ |
/* Check status for errors. |
*/ |
if (rx_bdp[i].len_status & (OETH_RX_BD_TOOLONG | |
OETH_RX_BD_SHORT)) { |
bad = 1; |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) { |
bad = 1; |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) { |
bad = 1; |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) { |
bad = 1; |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) { |
|
} |
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
bad = 1; |
} |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
bad = 1; |
} |
|
if (bad) { |
printf("RXE: 0x%x\n",rx_bdp[i].len_status & OETH_RX_BD_STATS); |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
bad = 0; |
continue; |
} |
else { |
if (bad) { |
printf("RXE: 0x%x\n",rx_bdp[i].len_status & |
OETH_RX_BD_STATS); |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
bad = 0; |
continue; |
} |
else { |
|
/* Process the incoming frame. |
*/ |
pkt_len = rx_bdp[i].len_status >> 16; |
/* Process the incoming frame. |
*/ |
pkt_len = rx_bdp[i].len_status >> 16; |
|
/* Do something here with the data - copy it into userspace, perhaps. */ |
// See if it's an ARP packet |
packet_check_arp_header((void *)rx_bdp[i].addr ); |
// See if it's an ICMP echo request |
packet_check_icmp_header((void *)rx_bdp[i].addr ); |
if (print_packet_contents) |
{ |
oeth_print_packet(rx_bdp[i].addr, rx_bdp[i].len_status >> 16); |
printf("\t end of packet\n\n"); |
} |
/* finish up */ |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; /* Clear stats */ |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; /* Mark RX BD as empty */ |
/* Do something here with the data - copy it |
into userspace, perhaps. */ |
// See if it's an ARP packet |
packet_check_arp_header((void*)rx_bdp[i].addr); |
// See if it's an ICMP echo request |
packet_check_icmp_header((void*)rx_bdp[i].addr); |
if (print_packet_contents) |
{ |
oeth_print_packet(i, rx_bdp[i].addr, |
rx_bdp[i].len_status |
>> 16); |
printf("\t end of packet\n\n"); |
} |
/* finish up */ |
/* Clear stats */ |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
/* Mark RX BD as empty */ |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
|
oeth_transmit_pause(); //try this! |
|
|
} |
} |
} |
} |
} |
} |
|
|
1828,33 → 2043,37
static void |
oeth_tx(void) |
{ |
volatile oeth_bd *tx_bd; |
int i; |
if (print_packet_contents) |
printf("tx"); |
volatile oeth_bd *tx_bd; |
int i; |
if (print_packet_contents) |
printf("tx"); |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
/* Go through the TX buffs, search for one that was just sent */ |
for(i = 0; i < OETH_TXBD_NUM; i++) |
{ |
/* Looking for buffer NOT ready for transmit. and IRQ enabled */ |
if( (!(tx_bd[i].len_status & (OETH_TX_BD_READY))) && (tx_bd[i].len_status & (OETH_TX_BD_IRQ)) ) |
/* Go through the TX buffs, search for one that was just sent */ |
for(i = 0; i < OETH_TXBD_NUM; i++) |
{ |
//oeth_print_packet(tx_bd[i].addr, (tx_bd[i].len_status >> 16)); |
/* Single threaded so no chance we have detected a buffer that has had its IRQ bit set but not its BD_READ flag. Maybe this won't work in linux */ |
tx_bd[i].len_status &= ~OETH_TX_BD_IRQ; |
/* Looking for buffer NOT ready for transmit. and IRQ enabled */ |
if( (!(tx_bd[i].len_status & (OETH_TX_BD_READY))) && |
(tx_bd[i].len_status & (OETH_TX_BD_IRQ)) ) |
{ |
/* Single threaded so no chance we have detected a |
buffer that has had its IRQ bit set but not its |
BD_READ flag. Maybe this won't work in linux */ |
tx_bd[i].len_status &= ~OETH_TX_BD_IRQ; |
|
/* Probably good to check for TX errors here */ |
// Check if either carrier sense lost or colission indicated |
if (tx_bd[i].len_status & OETH_TX_BD_STATS) |
printf("TXER: 0x%x\n",(tx_bd[i].len_status & OETH_TX_BD_STATS)); |
/* Probably good to check for TX errors here */ |
// Check if either carrier sense lost or colission |
// indicated |
if (tx_bd[i].len_status & OETH_TX_BD_STATS) |
printf("TXER: 0x%x\n", |
(tx_bd[i].len_status &OETH_TX_BD_STATS)); |
|
if (print_packet_contents) |
printf("T%d",i); |
if (print_packet_contents) |
printf("T%d",i); |
} |
} |
} |
return; |
return; |
} |
|
|
1861,126 → 2080,157
int main () |
{ |
|
print_packet_contents = 0; // Default to not printing packet contents. |
|
/* Initialise vector handler */ |
int_init(); |
print_packet_contents = 0; // Default to not printing packet contents. |
packet_inspect_debug = 0; |
print_ethmac_debug_reg = 0; |
|
/* Install ethernet interrupt handler, it is enabled here too */ |
int_add(ETH0_IRQ, oeth_interrupt, 0); |
/* Initialise vector handler */ |
int_init(); |
|
/* Enable interrupts */ |
cpu_enable_user_interrupts(); |
/* Install ethernet interrupt handler, it is enabled here too */ |
int_add(ETH0_IRQ, oeth_interrupt, 0); |
|
/* Enable interrupts */ |
cpu_enable_user_interrupts(); |
|
last_char=0; /* Variable init for spin_cursor() */ |
next_tx_buf_num = 4; /* init for tx buffer counter */ |
last_char=0; /* Variable init for spin_cursor() */ |
next_tx_buf_num = 4; /* init for tx buffer counter */ |
|
uart_init(DEFAULT_UART); // init the UART before we can printf |
printf("\n\teth ping program\n\n"); |
printf("\n\tboard IP: %d.%d.%d.%d\n",our_ip[0]&0xff,our_ip[1]&0xff, |
our_ip[2]&0xff,our_ip[3]&0xff); |
uart_init(DEFAULT_UART); // init the UART before we can printf |
printf("\n\teth ping program\n\n"); |
printf("\n\tboard IP: %d.%d.%d.%d\n",our_ip[0]&0xff,our_ip[1]&0xff, |
our_ip[2]&0xff,our_ip[3]&0xff); |
|
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX in MODER */ |
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX in |
MODER */ |
|
//scan_ethphys(); /* Scan MIIM bus for PHYs */ |
//ethphy_init(); /* Attempt reset and configuration of PHY via MIIM */ |
//ethmac_scanstatus(); /* Enable scanning of status register via MIIM */ |
//scan_ethphys(); /* Scan MIIM bus for PHYs */ |
//ethphy_init(); /* Attempt reset and configuration of PHY via MIIM */ |
//ethmac_scanstatus(); /* Enable scanning of status register via MIIM */ |
|
/* Loop, monitoring user input from TTY */ |
while(1) |
{ |
char c; |
|
while(!uart_check_for_char(DEFAULT_UART)) |
/* Loop, monitoring user input from TTY */ |
while(1) |
{ |
spin_cursor(); |
//oeth_monitor_rx(); |
} |
char c; |
|
c = uart_getc(DEFAULT_UART); |
while(!uart_check_for_char(DEFAULT_UART)) |
{ |
|
spin_cursor(); |
|
if (print_ethmac_debug_reg) |
oeth_print_wbdebug(); |
} |
|
c = uart_getc(DEFAULT_UART); |
|
if (c == 's') |
tx_packet((void*) ping_packet, 98); |
else if (c == 'S') |
tx_packet((void*)big_ping_packet, 1514); |
else if (c == 'h') |
scan_ethphys(); |
else if (c == 'i') |
ethphy_init(); |
else if (c == 'P') |
{ |
print_packet_contents = print_packet_contents ? 0 : 1; |
if (print_packet_contents) |
printf("Enabling packet dumping\n"); |
else |
printf("Packet dumping disabled\n"); |
} |
else if (c == 'p') |
oeth_printregs(); |
else if (c == '0') |
scan_ethphy(0); |
else if (c == '1') |
scan_ethphy(1); |
else if (c == '7') |
{ |
//scan_ethphy(7); |
//ethphy_print_status(7); |
printf("ext_sr 0x%x\n",eth_mii_read(0x7, 0x1b)); |
} |
else if (c == 'r') |
{ |
ethphy_reset(7); |
printf("PHY reset\n"); |
} |
else if (c == 'R') |
{ |
//oeth_reset_tx_bd_pointer(); |
ethmac_setup(); |
printf("MAC reset\n"); |
} |
else if (c == 'n') |
ethphy_reneg(7); |
else if (c == 'N') |
ethphy_set_autoneg(7); |
else if (c == 'm') |
ethmac_togglehugen(); |
else if (c == 't') |
ethphy_set_10mbit(0); |
else if (c == 'w') |
{ |
// Play with HWCFG mode of Alaska 88e1111 Phy |
c = uart_getc(DEFAULT_UART); |
short newvalue; |
// c is an ascii char, let's convert it to actual hex value |
if (c >= 'A' && c <= 'F') |
newvalue = c - (65 - 10); |
else if (c >= 'a' && c <= 'f') |
newvalue = c - (99 - 10); |
else if (c >= '0' && c <= '9') |
newvalue = c - 48; |
if (c == 's') |
tx_packet((void*) ping_packet, 98); |
else if (c == 'S') |
tx_packet((void*)big_ping_packet, 1514); |
else if (c == 'h') |
scan_ethphys(); |
else if (c == 'i') |
ethphy_init(); |
else if (c == 'c') |
oeth_ctrlmode_switch(); |
else if (c == 'P') |
{ |
print_packet_contents = print_packet_contents ? 0 : 1; |
if (print_packet_contents) |
printf("Enabling packet dumping\n"); |
else |
printf("Packet dumping disabled\n"); |
} |
else if (c == 'p') |
oeth_printregs(); |
else if (c == '0') |
scan_ethphy(0); |
else if (c == '1') |
scan_ethphy(1); |
else if (c == '7') |
{ |
//scan_ethphy(7); |
//ethphy_print_status(7); |
printf("ext_sr 0x%x\n",eth_mii_read(0x7, 0x1b)); |
} |
else if (c == 'r') |
{ |
ethphy_reset(7); |
printf("PHY reset\n"); |
} |
else if (c == 'R') |
{ |
//oeth_reset_tx_bd_pointer(); |
ethmac_setup(); |
printf("MAC reset\n"); |
} |
else if (c == 'n') |
ethphy_reneg(7); |
else if (c == 'N') |
ethphy_set_autoneg(7); |
else if (c == 'm') |
ethmac_togglehugen(); |
else if (c == 't') |
ethphy_set_10mbit(0); |
else if (c == 'w') |
{ |
// Play with HWCFG mode of Alaska 88e1111 Phy |
c = uart_getc(DEFAULT_UART); |
short newvalue; |
// c is an ascii char, let's convert it to actual hex |
// value |
if (c >= 'A' && c <= 'F') |
newvalue = c - (65 - 10); |
else if (c >= 'a' && c <= 'f') |
newvalue = c - (99 - 10); |
else if (c >= '0' && c <= '9') |
newvalue = c - 48; |
|
// Take this value and or it into the bottom bit (supposedly ext_sr) |
// Take this value and or it into the bottom bit |
// (supposedly ext_sr) |
#define MII_M1111_PHY_EXT_SR 0x1b |
short ext_sr; |
ext_sr = eth_mii_read(0x7, MII_M1111_PHY_EXT_SR); |
short ext_sr; |
ext_sr = eth_mii_read(0x7, MII_M1111_PHY_EXT_SR); |
#define MII_M1111_HWCFG_MODE_MASK 0xf |
ext_sr &= ~MII_M1111_HWCFG_MODE_MASK; |
ext_sr |= (short) newvalue; |
eth_mii_write(0x7, MII_M1111_PHY_EXT_SR, ext_sr); |
printf("ext_sr updated to - 0x%x\n",eth_mii_read(0x7, MII_M1111_PHY_EXT_SR)); |
} |
else if ( c == 'b' ) |
{ |
printf("\n\t---\n"); |
oeth_dump_bds(); |
printf("\t---\n"); |
} |
ext_sr &= ~MII_M1111_HWCFG_MODE_MASK; |
ext_sr |= (short) newvalue; |
eth_mii_write(0x7, MII_M1111_PHY_EXT_SR, ext_sr); |
printf("ext_sr updated to - 0x%x\n", |
eth_mii_read(0x7, MII_M1111_PHY_EXT_SR)); |
} |
else if ( c == 'b' ) |
{ |
printf("\n\t---\n"); |
oeth_dump_bds(); |
printf("\t---\n"); |
} |
|
else if ( c == 'B' ) |
{ |
tx_packet((void*) broadcast_ping_packet, 298); |
else if ( c == 'B' ) |
{ |
tx_packet((void*) broadcast_ping_packet, 298); |
} |
else if (c == 'u' ) |
oeth_transmit_pause(); |
else if (c == 'd' ) |
{ |
oeth_print_wbdebug(); |
print_ethmac_debug_reg = !print_ethmac_debug_reg; |
} |
else if (c == 'v' ) |
{ |
if (packet_inspect_debug) |
printf("Disabling "); |
else |
printf("Enabling "); |
|
printf("packet type announcments\n"); |
|
packet_inspect_debug = !packet_inspect_debug; |
} |
else if ( c == 'o' ) |
oeth_toggle_promiscuous(); |
|
} |
|
} |
|
} |
/tests/ethmac/sim/ethmac-rxtxcallresponse.c
5,10 → 5,6
//// Description //// |
//// Send packets while receiving packets //// |
//// //// |
//// Test data comes from pre-calculated array of random values, //// |
//// MAC TX buffer pointers are set to addresses in this array, //// |
//// saving copying the data around before transfers. //// |
//// //// |
//// Author(s): //// |
//// - jb, jb@orsoc.se, with parts taken from Linux kernel //// |
//// open_eth driver. //// |
479,6 → 475,7
report(0xbaad0004); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) { |
// not necessarily an issue |
report(0xbaad0005); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
636,7 → 633,7
send_ethmac_rxtx_test_init_packet(0x0); // 0x0 - call response test |
|
#define ETH_TX_MIN_PACKET_SIZE 512 |
#define ETH_TX_NUM_PACKETS (ETH_TX_MIN_PACKET_SIZE + 20) |
#define ETH_TX_NUM_PACKETS 20 |
|
//int response_time = 150000; // Response time before response packet it sent |
// back (should be in nanoseconds). |
644,7 → 641,7
|
unsigned long num_to_check; |
for(num_to_check=ETH_TX_MIN_PACKET_SIZE; |
num_to_check<ETH_TX_NUM_PACKETS; |
num_to_check<ETH_TX_MIN_PACKET_SIZE + ETH_TX_NUM_PACKETS; |
num_to_check++) |
fill_and_tx_call_packet(num_to_check, response_time); |
|
660,7 → 657,7
oeth_enable_rx(); |
|
for(num_to_check=ETH_TX_MIN_PACKET_SIZE; |
num_to_check<ETH_TX_NUM_PACKETS; |
num_to_check<ETH_TX_MIN_PACKET_SIZE + ETH_TX_NUM_PACKETS; |
num_to_check++) |
fill_and_tx_call_packet(num_to_check, response_time); |
|
/tests/ethmac/sim/ethmac-rxtxoverflow.c
0,0 → 1,602
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Interrupt-driven Ethernet MAC transmit test code //// |
//// //// |
//// Description //// |
//// Attempt to overflow the RX path in MAC //// |
//// //// |
//// Author(s): //// |
//// - jb, jb@orsoc.se, with parts taken from Linux kernel //// |
//// open_eth driver. //// |
//// //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
//// //// |
//// Copyright (C) 2009 Authors and OPENCORES.ORG //// |
//// //// |
//// This source file may be used and distributed without //// |
//// restriction provided that this copyright statement is not //// |
//// removed from the file and that any derivative work contains //// |
//// the original copyright notice and the associated disclaimer. //// |
//// //// |
//// This source file is free software; you can redistribute it //// |
//// and/or modify it under the terms of the GNU Lesser General //// |
//// Public License as published by the Free Software Foundation; //// |
//// either version 2.1 of the License, or (at your option) any //// |
//// later version. //// |
//// //// |
//// This source is distributed in the hope that it will be //// |
//// useful, but WITHOUT ANY WARRANTY; without even the implied //// |
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //// |
//// PURPOSE. See the GNU Lesser General Public License for more //// |
//// details. //// |
//// //// |
//// You should have received a copy of the GNU Lesser General //// |
//// Public License along with this source; if not, download it //// |
//// from http://www.opencores.org/lgpl.shtml //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
// Test sends the test code (0x1) for overflow test in first packet, which is |
// read by Verilog stimulus module. |
|
// SW is setup to echo back all packets it receives. TB sends 16 packets, as |
// fast as possible, which should saturate the MAC's buffers. |
// TB then waits for a BD to be ready and sends one more packet, and ensures |
// that arrives in memory OK. |
// Test is over when this software manages to send back 4 reply packets. |
|
#include "cpu-utils.h" |
#include "board.h" |
#include "int.h" |
#include "ethmac.h" |
#include "eth-phy-mii.h" |
|
volatile unsigned tx_done; |
volatile unsigned rx_done; |
static int next_tx_buf_num; |
|
/* Functions in this file */ |
void ethmac_setup(void); |
/* Interrupt functions */ |
void oeth_interrupt(void); |
static void oeth_rx(void); |
static void oeth_tx(void); |
|
/* Let the ethernet packets use a space beginning here for buffering */ |
#define ETH_BUFF_BASE 0x01000000 |
|
|
#define RXBUFF_PREALLOC 1 |
#define TXBUFF_PREALLOC 1 |
//#undef RXBUFF_PREALLOC |
//#undef TXBUFF_PREALLOC |
|
/* The transmitter timeout |
*/ |
#define TX_TIMEOUT (2*HZ) |
|
/* Buffer number (must be 2^n) |
*/ |
#define OETH_RXBD_NUM 16 |
#define OETH_TXBD_NUM 16 |
#define OETH_RXBD_NUM_MASK (OETH_RXBD_NUM-1) |
#define OETH_TXBD_NUM_MASK (OETH_TXBD_NUM-1) |
|
/* Buffer size |
*/ |
#define OETH_RX_BUFF_SIZE 0x600-4 |
#define OETH_TX_BUFF_SIZE 0x600-4 |
|
/* Buffer size (if not XXBUF_PREALLOC |
*/ |
#define MAX_FRAME_SIZE 1518 |
|
/* The buffer descriptors track the ring buffers. |
*/ |
struct oeth_private { |
//struct sk_buff* rx_skbuff[OETH_RXBD_NUM]; |
//struct sk_buff* tx_skbuff[OETH_TXBD_NUM]; |
|
unsigned short tx_next; /* Next buffer to be sent */ |
unsigned short tx_last; /* Next buffer to be checked if packet sent */ |
unsigned short tx_full; /* Buffer ring fuul indicator */ |
unsigned short rx_cur; /* Next buffer to be checked if packet |
received */ |
|
oeth_regs *regs; /* Address of controller registers. */ |
oeth_bd *rx_bd_base; /* Address of Rx BDs. */ |
oeth_bd *tx_bd_base; /* Address of Tx BDs. */ |
|
// struct net_device_stats stats; |
}; |
|
#define PHYNUM 7 |
|
void |
eth_mii_write(char phynum, short regnum, short data) |
{ |
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE); |
regs->miiaddress = (regnum << 8) | phynum; |
regs->miitx_data = data; |
regs->miicommand = OETH_MIICOMMAND_WCTRLDATA; |
regs->miicommand = 0; |
while(regs->miistatus & OETH_MIISTATUS_BUSY); |
} |
|
short |
eth_mii_read(char phynum, short regnum) |
{ |
static volatile oeth_regs *regs = (oeth_regs *)(OETH_REG_BASE); |
regs->miiaddress = (regnum << 8) | phynum; |
regs->miicommand = OETH_MIICOMMAND_RSTAT; |
regs->miicommand = 0; |
while(regs->miistatus & OETH_MIISTATUS_BUSY); |
|
return regs->miirx_data; |
} |
|
|
|
// Wait here until all packets have been transmitted |
void |
wait_until_all_tx_clear(void) |
{ |
int i; |
volatile oeth_bd *tx_bd; |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
int some_tx_waiting = 1; |
|
while (some_tx_waiting) |
{ |
some_tx_waiting = 0; |
/* Go through the TX buffs, search for unused one */ |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
|
// Looking for buffer ready for transmit |
if((tx_bd[i].len_status & OETH_TX_BD_READY)) |
some_tx_waiting = 1; |
|
} |
} |
} |
|
|
void |
ethphy_set_10mbit(int phynum) |
{ |
wait_until_all_tx_clear(); |
// Hardset PHY to just use 10Mbit mode |
short cr = eth_mii_read(phynum, MII_BMCR); |
cr &= ~BMCR_ANENABLE; // Clear auto negotiate bit |
cr &= ~BMCR_SPEED100; // Clear fast eth. bit |
eth_mii_write(phynum, MII_BMCR, cr); |
} |
|
|
void |
ethphy_set_100mbit(int phynum) |
{ |
wait_until_all_tx_clear(); |
// Hardset PHY to just use 100Mbit mode |
short cr = eth_mii_read(phynum, MII_BMCR); |
cr |= BMCR_ANENABLE; // Clear auto negotiate bit |
cr |= BMCR_SPEED100; // Clear fast eth. bit |
eth_mii_write(phynum, MII_BMCR, cr); |
} |
|
|
void |
ethmac_setup(void) |
{ |
// from arch/or32/drivers/open_eth.c |
volatile oeth_regs *regs; |
|
regs = (oeth_regs *)(OETH_REG_BASE); |
|
/* Reset MII mode module */ |
regs->miimoder = OETH_MIIMODER_RST; /* MII Reset ON */ |
regs->miimoder &= ~OETH_MIIMODER_RST; /* MII Reset OFF */ |
regs->miimoder = 0x64; /* Clock divider for MII Management interface */ |
|
/* Reset the controller. |
*/ |
regs->moder = OETH_MODER_RST; /* Reset ON */ |
regs->moder &= ~OETH_MODER_RST; /* Reset OFF */ |
|
/* Setting TXBD base to OETH_TXBD_NUM. |
*/ |
regs->tx_bd_num = OETH_TXBD_NUM; |
|
|
/* Set min/max packet length |
*/ |
regs->packet_len = 0x00400600; |
|
/* Set IPGT register to recomended value |
*/ |
regs->ipgt = 0x12; |
|
/* Set IPGR1 register to recomended value |
*/ |
regs->ipgr1 = 0x0000000c; |
|
/* Set IPGR2 register to recomended value |
*/ |
regs->ipgr2 = 0x00000012; |
|
/* Set COLLCONF register to recomended value |
*/ |
regs->collconf = 0x000f003f; |
|
/* Set control module mode |
*/ |
#if 0 |
regs->ctrlmoder = OETH_CTRLMODER_TXFLOW | OETH_CTRLMODER_RXFLOW; |
#else |
regs->ctrlmoder = 0; |
#endif |
|
/* Clear MIIM registers */ |
regs->miitx_data = 0; |
regs->miiaddress = 0; |
regs->miicommand = 0; |
|
regs->mac_addr1 = ETH_MACADDR0 << 8 | ETH_MACADDR1; |
regs->mac_addr0 = ETH_MACADDR2 << 24 | ETH_MACADDR3 << 16 | ETH_MACADDR4 << 8 | ETH_MACADDR5; |
|
/* Clear all pending interrupts |
*/ |
regs->int_src = 0xffffffff; |
|
/* Promisc, IFG, CRCEn |
*/ |
regs->moder |= OETH_MODER_PRO | OETH_MODER_PAD | OETH_MODER_IFG | OETH_MODER_CRCEN | OETH_MODER_FULLD; |
|
/* Enable interrupt sources. |
*/ |
|
regs->int_mask = OETH_INT_MASK_TXB | |
OETH_INT_MASK_TXE | |
OETH_INT_MASK_RXF | |
OETH_INT_MASK_RXE | |
OETH_INT_MASK_BUSY | |
OETH_INT_MASK_TXC | |
OETH_INT_MASK_RXC; |
|
// Buffer setup stuff |
volatile oeth_bd *tx_bd, *rx_bd; |
int i,j,k; |
|
/* Initialize TXBD pointer |
*/ |
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
|
/* Initialize RXBD pointer |
*/ |
rx_bd = ((volatile oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
/* Preallocated ethernet buffer setup */ |
unsigned long mem_addr = ETH_BUFF_BASE; /* Defined at top */ |
|
// Setup TX Buffers |
for(i = 0; i < OETH_TXBD_NUM; i++) { |
//tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC | OETH_RX_BD_IRQ; |
tx_bd[i].len_status = OETH_TX_BD_PAD | OETH_TX_BD_CRC; |
tx_bd[i].addr = mem_addr; |
mem_addr += OETH_TX_BUFF_SIZE; |
} |
tx_bd[OETH_TXBD_NUM - 1].len_status |= OETH_TX_BD_WRAP; |
|
// Setup RX buffers |
for(i = 0; i < OETH_RXBD_NUM; i++) { |
rx_bd[i].len_status = OETH_RX_BD_EMPTY | OETH_RX_BD_IRQ; // Init. with IRQ |
rx_bd[i].addr = mem_addr; |
mem_addr += OETH_RX_BUFF_SIZE; |
} |
rx_bd[OETH_RXBD_NUM - 1].len_status |= OETH_RX_BD_WRAP; // Last buffer wraps |
|
/* Enable RX and TX in MAC |
*/ |
regs->moder &= ~(OETH_MODER_RXEN | OETH_MODER_TXEN); |
regs->moder |= OETH_MODER_RXEN | OETH_MODER_TXEN; |
|
next_tx_buf_num = 0; // init tx buffer pointer |
|
return; |
} |
|
// Enable RX in ethernet MAC |
void |
oeth_enable_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
regs->moder |= OETH_MODER_RXEN; |
} |
|
// Disable RX in ethernet MAC |
void |
oeth_disable_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
regs->moder &= ~(OETH_MODER_RXEN); |
} |
|
|
/* Setup buffer descriptors with data */ |
/* length is in BYTES */ |
void tx_packet(void* data, int length) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *tx_bd; |
volatile int i; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; |
tx_bd = (struct oeth_bd*) &tx_bd[next_tx_buf_num]; |
|
// If it's in use - wait |
while ((tx_bd->len_status & OETH_TX_BD_IRQ)); |
|
/* Clear all of the status flags. |
*/ |
tx_bd->len_status &= ~OETH_TX_BD_STATS; |
|
/* If the frame is short, tell CPM to pad it. |
*/ |
#define ETH_ZLEN 60 /* Min. octets in frame sans FCS */ |
if (length <= ETH_ZLEN) |
tx_bd->len_status |= OETH_TX_BD_PAD; |
else |
tx_bd->len_status &= ~OETH_TX_BD_PAD; |
|
if ((int) data != 0){ |
//Copy the data into the transmit buffer, byte at a time |
char* data_p = (char*) data; |
char* data_b = (char*) tx_bd->addr; |
for(i=0;i<length;i++) |
{ |
data_b[i] = data_p[i]; |
} |
} |
|
/* Set the length of the packet's data in the buffer descriptor */ |
tx_bd->len_status = (tx_bd->len_status & 0x0000ffff) | |
((length&0xffff) << 16); |
|
/* Send it on its way. Tell controller its ready, interrupt when sent |
* and to put the CRC on the end. |
*/ |
tx_bd->len_status |= (OETH_TX_BD_READY | OETH_TX_BD_CRC | OETH_TX_BD_IRQ); |
|
next_tx_buf_num = (next_tx_buf_num + 1) & OETH_TXBD_NUM_MASK; |
|
tx_done++; |
|
// This test over after 4 packets sent. |
if (tx_done == 4) |
{ |
report(0x8000000d); |
exit(0); |
} |
|
return; |
|
|
} |
|
/* The interrupt handler. |
*/ |
void |
oeth_interrupt(void) |
{ |
|
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
uint int_events; |
int serviced; |
|
serviced = 0; |
|
/* Get the interrupt events that caused us to be here. |
*/ |
int_events = regs->int_src; |
regs->int_src = int_events; |
|
/* Handle receive event in its own function. |
*/ |
if (int_events & (OETH_INT_RXF | OETH_INT_RXE)) { |
serviced |= 0x1; |
oeth_rx(); |
} |
|
/* Handle transmit event in its own function. |
*/ |
if (int_events & (OETH_INT_TXB | OETH_INT_TXE)) { |
serviced |= 0x2; |
oeth_tx(); |
serviced |= 0x2; |
|
} |
|
/* Check for receive busy, i.e. packets coming but no place to |
* put them. |
*/ |
if (int_events & OETH_INT_BUSY) { |
serviced |= 0x4; |
if (!(int_events & (OETH_INT_RXF | OETH_INT_RXE))) |
oeth_rx(); |
} |
|
return; |
} |
|
|
|
static void |
oeth_rx(void) |
{ |
volatile oeth_regs *regs; |
regs = (oeth_regs *)(OETH_REG_BASE); |
|
volatile oeth_bd *rx_bdp; |
int pkt_len, i; |
int bad = 0; |
|
rx_bdp = ((oeth_bd *)OETH_BD_BASE) + OETH_TXBD_NUM; |
|
|
/* Find RX buffers marked as having received data */ |
for(i = 0; i < OETH_RXBD_NUM; i++) |
{ |
bad=0; |
if(!(rx_bdp[i].len_status & OETH_RX_BD_EMPTY)){ /* Looking for NOT empty buffers desc. */ |
/* Check status for errors. |
*/ |
if (rx_bdp[i].len_status & (OETH_RX_BD_TOOLONG | OETH_RX_BD_SHORT)) { |
bad = 1; |
report(0xbaad0001); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_DRIBBLE) { |
bad = 1; |
report(0xbaad0002); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_CRCERR) { |
bad = 1; |
report(0xbaad0003); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_OVERRUN) { |
bad = 1; |
report(0xbaad0004); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_MISS) { |
// not necessarily an issue |
report(0xbaad0005); |
} |
if (rx_bdp[i].len_status & OETH_RX_BD_LATECOL) { |
bad = 1; |
report(0xbaad0006); |
} |
if (bad) { |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; |
exit(0xbaaaaaad); |
|
continue; |
} |
else { |
/* Process the incoming frame. |
*/ |
pkt_len = rx_bdp[i].len_status >> 16; |
|
// Attempt to transmit it back |
tx_packet((void*)rx_bdp[i].addr,pkt_len); |
|
/* finish up */ |
rx_bdp[i].len_status &= ~OETH_RX_BD_STATS; /* Clear stats */ |
rx_bdp[i].len_status |= OETH_RX_BD_EMPTY; /* Mark RX BD as empty */ |
rx_done++; |
} |
} |
} |
} |
|
|
|
static void |
oeth_tx(void) |
{ |
volatile oeth_bd *tx_bd; |
int i; |
|
tx_bd = (volatile oeth_bd *)OETH_BD_BASE; /* Search from beginning*/ |
|
/* Go through the TX buffs, search for one that was just sent */ |
for(i = 0; i < OETH_TXBD_NUM; i++) |
{ |
/* Looking for buffer NOT ready for transmit. and IRQ enabled */ |
if( (!(tx_bd[i].len_status & (OETH_TX_BD_READY))) && (tx_bd[i].len_status & (OETH_TX_BD_IRQ)) ) |
{ |
/* Single threaded so no chance we have detected a buffer that has had its IRQ bit set but not its BD_READ flag. Maybe this won't work in linux */ |
tx_bd[i].len_status &= ~OETH_TX_BD_IRQ; |
|
/* Probably good to check for TX errors here */ |
|
/* set our test variable */ |
tx_done++; |
|
// This test over after 4 packets sent. |
if (tx_done == 4) |
{ |
report(0x8000000d); |
exit(0); |
} |
|
} |
} |
return; |
} |
|
// Send a packet, the very first byte of which will be read by the testbench |
// and used to indicate which test we'll use. |
static char cmd_tx_buffer[40]; |
void |
send_ethmac_rxtx_test_init_packet(char test) |
{ |
int i; |
|
cmd_tx_buffer[0] = test; |
// Clear rest of buffer |
for(i=0;i<40;i++) cmd_tx_buffer[i] = test; |
tx_packet(cmd_tx_buffer, 40); // Smallest packet that can be sent |
} |
|
// Loop to check if a number is prime by doing mod divide of the number |
// to test by every number less than it |
int |
is_prime_number(unsigned long n) |
{ |
unsigned long c; |
if (n < 2) return 0; |
for(c=2;c<n;c++) |
if ((n % c) == 0) |
return 0; |
return 1; |
} |
|
|
int |
main () |
{ |
|
/* Initialise handler vector */ |
int_init(); |
|
/* Install ethernet interrupt handler, it is enabled here too */ |
int_add(ETH0_IRQ, oeth_interrupt, 0); |
|
/* Enable interrupts in supervisor register */ |
cpu_enable_user_interrupts(); |
|
/* Enable CPU timer */ |
cpu_enable_timer(); |
|
ethmac_setup(); /* Configure MAC, TX/RX BDs and enable RX and TX */ |
|
/* clear tx_done, the tx interrupt handler will set it when it's been |
transmitted */ |
tx_done = 0; |
rx_done = 0; |
|
ethphy_set_100mbit(0); |
|
send_ethmac_rxtx_test_init_packet(0x1); // 0x1 - overflow test |
|
while(1); // Sit and wait for test to finish in interrupt-triggered code |
|
} |
/tests/or1200/sim/or1200-cy.S
102,7 → 102,7
|
.global _start |
_start: |
// Clear all regs |
// Clear regs |
l.movhi r1, 0 |
l.movhi r2, 0 |
l.movhi r3, 0 |
109,31 → 109,6
l.movhi r4, 0 |
l.movhi r5, 0 |
l.movhi r6, 0 |
l.movhi r7, 0 |
l.movhi r8, 0 |
l.movhi r9, 0 |
l.movhi r10, 0 |
l.movhi r11, 0 |
l.movhi r12, 0 |
l.movhi r13, 0 |
l.movhi r14, 0 |
l.movhi r15, 0 |
l.movhi r16, 0 |
l.movhi r17, 0 |
l.movhi r18, 0 |
l.movhi r19, 0 |
l.movhi r20, 0 |
l.movhi r21, 0 |
l.movhi r22, 0 |
l.movhi r23, 0 |
l.movhi r24, 0 |
l.movhi r25, 0 |
l.movhi r26, 0 |
l.movhi r27, 0 |
l.movhi r28, 0 |
l.movhi r29, 0 |
l.movhi r30, 0 |
l.movhi r31, 0 |
|
#ifdef OR1200_IMPL_CY |
// Kick off test |
149,16 → 124,16
|
|
#define CHECK_CY_CLEAR \ |
l.mfspr r20, r0, SPR_SR ; \ |
l.andi r21, r20, SPR_SR_CY ; \ |
l.sfne r21, r0 ; \ |
l.mfspr r6, r0, SPR_SR ; \ |
l.andi r6, r6, SPR_SR_CY ; \ |
l.sfne r6, r0 ; \ |
l.bf _fail ; \ |
l.nop |
|
#define CHECK_CY_SET \ |
l.mfspr r20, r0, SPR_SR ; \ |
l.andi r21, r20, SPR_SR_CY ; \ |
l.sfnei r21, SPR_SR_CY ; \ |
l.mfspr r6, r0, SPR_SR ; \ |
l.andi r6, r6, SPR_SR_CY ; \ |
l.sfnei r6, SPR_SR_CY ; \ |
l.bf _fail ; \ |
l.nop |
|
/tests/or1200/sim/or1200-basic.S
83,110 → 83,9
|
.global _start |
_start: |
|
/* Instruction cache enable */ |
/* Check if IC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_ICP |
l.sfeq r26,r0 |
l.bf .L8 |
l.jal _cache_init |
l.nop |
|
/* Disable IC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_ICE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
|
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_ICCFGR |
l.andi r26,r24,SPR_ICCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
|
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_ICCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
|
/* Invalidate IC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
|
.L7: |
l.mtspr r0,r6,SPR_ICBIR |
l.sfne r6,r5 |
l.bf .L7 |
l.add r6,r6,r14 |
|
/* Enable IC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_ICE |
l.mtspr r0,r6,SPR_SR |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
|
.L8: |
/* Data cache enable */ |
/* Check if DC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_DCP |
l.sfeq r26,r0 |
l.bf .L10 |
l.nop |
/* Disable DC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_DCE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_DCCFGR |
l.andi r26,r24,SPR_DCCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_DCCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
/* Invalidate DC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
.L9: |
l.mtspr r0,r6,SPR_DCBIR |
l.sfne r6,r5 |
l.bf .L9 |
l.add r6,r6,r14 |
/* Enable DC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_DCE |
l.mtspr r0,r6,SPR_SR |
.L10: |
// Kick off test |
l.jal _main |
l.nop |
1100,4 → 999,5
l.nop 0x2 |
l.ori r3, r0, 0 /* Clear R3 */ |
l.nop 0x1 /* Exit simulation */ |
|
l.nop |
l.nop |
/tests/or1200/sim/or1200-intsyscall.S
8,9 → 8,9
Within the test we'll use following global variables: |
|
r15 syscall interrupt counter |
r16 syscall function counter |
r17 irq interrupt counter |
r18 intgen's base address |
r6 syscall function counter |
r10 irq interrupt counter |
r12 intgen's base address |
|
|
The test does the following: |
77,15 → 77,15
.org 0x800 |
.global _user_irq_handler |
_user_irq_handler: |
l.addi r17, r17, 1 |
l.addi r10, r10, 1 |
/* Report values , 0x00000800 == user interrupt report*/ |
l.ori r3, r0, 0x0800 |
l.nop 2 |
l.or r3, r0, r17 |
l.or r3, r0, r10 |
l.nop 2 |
/* TODO - propably confirm it was intgen's IRQ that caused this */ |
/* Clear interrupt source */ |
l.ori r7, r18, 0x1 /* intgen IRQ clear address */ |
l.ori r7, r12, 0x1 /* intgen IRQ clear address */ |
l.sb 0(r7), r0 /* Any write clears the bit */ |
/* Clear OR1200 PICSR */ |
l.mfspr r7, r0, SPR_PICSR |
107,7 → 107,7
l.xor r5, r5, r4 |
l.and r5, r7, r5 /* New SR without interrupt bits set */ |
l.mtspr r0, r5, SPR_ESR_BASE /* SR after l.rfe */ |
/* Report values , 0x00000c00 == tick timer report*/ |
/* Report values , 0x00000c00 == system call report*/ |
l.ori r3, r0, 0x0c00 |
l.nop 2 |
/* Get syscall number */ |
135,9 → 135,6
/* =================================================== [ main ] === */ |
.global _main |
_main: |
l.movhi r15, 0 |
l.movhi r16, 0 |
l.movhi r17, 0 |
|
# |
# unmask (enable) all ints |
151,13 → 148,18
l.ori r6,r6,SPR_SR_IEE |
l.mtspr r0,r6,SPR_SR |
|
l.movhi r15, 0 |
l.movhi r6, 0 |
l.movhi r10, 0 |
|
|
|
// Assumes r18 is intgen's base address |
l.movhi r18,hi(INTGEN_BASE) |
// Assumes r12 is intgen's base address |
l.movhi r12,hi(INTGEN_BASE) |
|
#define INTGEN_LOAD(x) \ |
l.ori r5,r0,lo(x) ;\ |
l.sb 0(r18),r5 |
l.sb 0(r12),r5 |
|
|
/* Test begin */ |
179,11 → 181,11
l.nop |
l.ori r5,r0,1 |
l.sys 0x5 |
l.sb 0(r18),r5 |
l.sb 0(r12),r5 |
l.nop |
l.nop |
l.nop |
l.sfnei r16, 0xf /* Should equal 15, 0xf */ |
l.sfnei r6, 0xf /* Should equal 15, 0xf */ |
l.bf _fail |
l.nop |
|
204,15 → 206,15
/* We'll restore them now */ |
l.mtspr r0, r7, SPR_ESR_BASE /* SR before syscall */ |
l.mtspr r0, r8, SPR_EPCR_BASE |
l.add r16, r16, r3 /* Add syscall number to our counter */ |
l.add r6, r6, r3 /* Add syscall number to our counter */ |
l.movhi r4, hi(0x00400000) /* 4MB mark of memory */ |
/* Ensure memory access OK */ |
l.slli r3, r3, 2 /* Turn syscall number into a word address (<< 2) */ |
l.add r4, r4, r3 /* Access this offset from 4MB mark */ |
l.sw 0(r4), r16 /* Do a write to memory */ |
l.lwz r16, 0(r4) /* Do a read from memory */ |
l.sw 0(r4), r6 /* Do a write to memory */ |
l.lwz r6, 0(r4) /* Do a read from memory */ |
/* Report running value of syscall counter */ |
l.or r3, r0, r16 |
l.or r3, r0, r6 |
l.nop 2 |
l.rfe /* Now continue from where we had the l.sys */ |
|
/tests/or1200/sim/or1200-except.S
95,7 → 95,7
l.mfspr r3,r0,SPR_EEAR_BASE /* Get EEA */ |
l.nop 2 |
l.addi r11,r11,1 /* Increment 1st exception counter */ |
l.sfeqi r30, 0xd /* Is this a data bus test, if so return with l.rfe */ |
l.sfeqi r2, 0xd /* Is this a data bus test, if so return with l.rfe */ |
l.bf 1f |
l.movhi r5, 0 /* r5 should be the one causing the error on dbus */ |
/* Instruction bus error test return */ |
138,27 → 138,32
.global _dtlb_handler |
/* Exception handler - DMMU TLB miss */ |
/* Assume 64-entry TLB cache */ |
_dtlb_handler: |
l.mfspr r20, r0, SPR_EEAR_BASE |
_dtlb_handler: |
l.sw -4(r1),r4 |
l.sw -8(r1),r5 |
l.sw -12(r1),r6 |
l.sw -16(r1),r7 |
l.sw -20(r1),r8 |
l.mfspr r2, r0, SPR_EEAR_BASE |
/* Find the entry/set for this address */ |
l.srli r21, r20, 13 /* r21 = VPN, shift by size 8192 = 2**13 */ |
l.andi r22, r21, 0x3f /* 64 entries = 6 bit mask, r22 = set number */ |
l.srli r13, r2, 13 /* r13 = VPN, shift by size 8192 = 2**13 */ |
l.andi r4, r13, 0x3f /* 64 entries = 6 bit mask, r4 = set number */ |
/* If page is in the 0xc0000000 space we map to 16MB part of |
memory, ie 0x0 => 0x01000000, otherwise 1-1 mapping */ |
l.movhi r23, hi(0xc0000000) |
l.ori r23, r23, lo(0xc0000000) |
l.srli r23, r23, 13 /* Get page address, shift by page size, 13 bits */ |
l.movhi r24, hi(0xff << 11) /* Mask for top byte of VPN */ |
l.ori r24, r24, lo(0xff << 11) |
l.and r24, r24, r21 /* Mask in only top byte of VPN */ |
l.sfeq r23, r24 /* Decide if it's in our special mapped region or not*/ |
l.movhi r5, hi(0xc0000000) |
l.ori r5, r5, lo(0xc0000000) |
l.srli r5, r5, 13 /* Get page address, shift by page size, 13 bits */ |
l.movhi r6, hi(0xff << 11) /* Mask for top byte of VPN */ |
l.ori r6, r6, lo(0xff << 11) |
l.and r6, r6, r13 /* Mask in only top byte of VPN */ |
l.sfeq r5, r6 /* Decide if it's in our special mapped region or not*/ |
|
/* First, Setup value for DTLBM (match) reg, is same for both cases */ |
l.movhi r24, hi(SPR_ITLBMR_VPN) /* VPN mask into r24 */ |
l.ori r24, r24, lo(SPR_ITLBMR_VPN) |
l.and r25, r20, r24 /* AND address with VPN mask */ |
l.ori r25, r25, SPR_DTLBMR_V /* OR in valid bit */ |
l.mtspr r22, r25, SPR_DTLBMR_BASE(0) /* Write to DTLBR register */ |
l.movhi r6, hi(SPR_ITLBMR_VPN) /* VPN mask into r6 */ |
l.ori r6, r6, lo(SPR_ITLBMR_VPN) |
l.and r7, r2, r6 /* AND address with VPN mask */ |
l.ori r7, r7, SPR_DTLBMR_V /* OR in valid bit */ |
l.mtspr r4, r7, SPR_DTLBMR_BASE(0) /* Write to DTLBR register */ |
|
l.bf _highmem_map |
l.nop |
166,31 → 171,35
_lomem_map: |
/* Do 1:1 mapping for this request */ |
/* Setup value for translate register */ |
l.movhi r24, hi(SPR_ITLBTR_PPN) /* PPN mask into r24 */ |
l.ori r24, r24, lo(SPR_ITLBTR_PPN) |
l.and r25, r20, r24 /* AND address with PPN mask */ |
l.ori r25, r25, DTLB_PR_NOLIMIT /* Set all execute enables, no lims. */ |
l.mtspr r22, r25, SPR_DTLBTR_BASE(0) /* Write to DTLTR register */ |
l.movhi r6, hi(SPR_ITLBTR_PPN) /* PPN mask into r6 */ |
l.ori r6, r6, lo(SPR_ITLBTR_PPN) |
l.and r7, r2, r6 /* AND address with PPN mask */ |
l.ori r7, r7, DTLB_PR_NOLIMIT /* Set all execute enables, no lims. */ |
l.mtspr r4, r7, SPR_DTLBTR_BASE(0) /* Write to DTLTR register */ |
l.j _dtlb_done |
l.addi r18, r18, 1 /* Incremement low-mapping counter */ |
l.addi r14, r14, 1 /* Incremement low-mapping counter */ |
|
_highmem_map: |
/* Do top byte, 0xc0->0x01, mapping for this request */ |
/* Setup value for translate register */ |
l.movhi r24, hi(SPR_ITLBTR_PPN) /* PPN mask into r24 */ |
l.ori r24, r24, lo(SPR_ITLBTR_PPN) |
l.and r25, r20, r24 /* AND address with PPN mask */ |
l.movhi r26, hi(0xff000000) /* Top byte address mask */ |
l.or r25, r26, r25 /* Set top byte to 0xff */ |
l.xor r25, r26, r25 /* Now clear top byte with XOR */ |
l.movhi r26, hi(0x01000000) /* Top address byte */ |
l.or r25, r26, r25 /* Set top address byte */ |
l.ori r25, r25, DTLB_PR_NOLIMIT /* Set all execute enables, no lims. */ |
l.mtspr r22, r25, SPR_DTLBTR_BASE(0) /* Write to DTLTR register */ |
l.addi r19, r19, 1 /* Incremement low-mapping counter */ |
l.movhi r6, hi(SPR_ITLBTR_PPN) /* PPN mask into r6 */ |
l.ori r6, r6, lo(SPR_ITLBTR_PPN) |
l.and r7, r2, r6 /* AND address with PPN mask */ |
l.movhi r8, hi(0xff000000) /* Top byte address mask */ |
l.or r7, r8, r7 /* Set top byte to 0xff */ |
l.xor r7, r8, r7 /* Now clear top byte with XOR */ |
l.movhi r8, hi(0x01000000) /* Top address byte */ |
l.or r7, r8, r7 /* Set top address byte */ |
l.ori r7, r7, DTLB_PR_NOLIMIT /* Set all execute enables, no lims. */ |
l.mtspr r4, r7, SPR_DTLBTR_BASE(0) /* Write to DTLTR register */ |
l.addi r15, r15, 1 /* Incremement low-mapping counter */ |
|
_dtlb_done: |
|
l.lwz r4,-4(r1) |
l.lwz r5,-8(r1) |
l.lwz r6,-12(r1) |
l.lwz r7,-16(r1) |
l.lwz r8,-20(r1) |
l.rfe |
|
|
202,110 → 211,8
|
.global _start |
_start: |
|
/* Instruction cache enable */ |
/* Check if IC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_ICP |
l.sfeq r26,r0 |
l.bf .L8 |
l.jal _cache_init |
l.nop |
|
/* Disable IC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_ICE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
|
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_ICCFGR |
l.andi r26,r24,SPR_ICCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
|
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_ICCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
|
/* Invalidate IC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
|
.L7: |
l.mtspr r0,r6,SPR_ICBIR |
l.sfne r6,r5 |
l.bf .L7 |
l.add r6,r6,r14 |
|
/* Enable IC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_ICE |
l.mtspr r0,r6,SPR_SR |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
|
.L8: |
/* Data cache enable */ |
/* Check if DC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_DCP |
l.sfeq r26,r0 |
l.bf .L10 |
l.nop |
/* Disable DC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_DCE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_DCCFGR |
l.andi r26,r24,SPR_DCCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_DCCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
/* Invalidate DC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
.L9: |
l.mtspr r0,r6,SPR_DCBIR |
l.sfne r6,r5 |
l.bf .L9 |
l.add r6,r6,r14 |
/* Enable DC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_DCE |
l.mtspr r0,r6,SPR_SR |
.L10: |
// Kick off test |
l.jal _main |
l.nop |
323,8 → 230,8
l.addi r11,r0,0 /* exception counter 1 */ |
l.addi r12,r0,0 /* exception counter 2 */ |
l.addi r13,r0,0 |
l.addi r18,r0,0 /* DMMU exception counter for low mem mapping */ |
l.addi r19,r0,0 /* DMMU exception counter for hi mem mapping */ |
l.addi r14,r0,0 /* DMMU exception counter for low mem mapping */ |
l.addi r15,r0,0 /* DMMU exception counter for hi mem mapping */ |
l.sw 0x0(r0),r0 /* Initialize RAM */ |
l.sw 0x4(r0),r0 /* Initialize RAM */ |
l.sw 0x8(r0),r0 /* Initialize RAM */ |
553,7 → 460,7
l.nop |
l.movhi r12, 0 /* Reset exception counters */ |
l.movhi r11, 0 |
l.ori r30, r0, 0xd /* put 0xd in r30, indicate it's databus test */ |
l.ori r2, r0, 0xd /* put 0xd in r2, indicate it's databus test */ |
/* Cause access error */ |
/* Load word */ |
l.movhi r5, 0xee00 /* Address to cause an error */ |
636,7 → 543,7
/* TODO: do this it with cache enabled/disabled */ |
l.movhi r12, 0 /* Reset exception counters */ |
l.movhi r11, 0 |
l.movhi r30, 0x0 /* put 0x0 in r30,indicate it's instruction bus test*/ |
l.movhi r2, 0x0 /* put 0x0 in r2,indicate it's instruction bus test*/ |
/* Cause access error */ |
l.movhi r5, 0xee00 /* Address to cause an error */ |
l.jalr r5 /* Jump and link to bad address */ |
673,10 → 580,10
l.movhi r7, hi(0xaabbccdd) |
l.ori r7, r7, lo(0xaabbccdd) |
l.sw 0(r5), r7 /* Shouldn't trigger MMU */ |
l.sfne r18, r0 |
l.sfne r14, r0 |
l.bf _dmmu_test_error |
l.nop |
l.sfne r19, r0 |
l.sfne r15, r0 |
l.bf _dmmu_test_error |
l.nop |
|
692,10 → 599,10
l.sfne r7, r8 |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r18, 0x1 /* Check for lo mem mapping */ |
l.sfnei r14, 0x1 /* Check for lo mem mapping */ |
l.bf _dmmu_test_error |
l.nop |
l.sfne r19, r0 /* hi-mem counter should still be 0 */ |
l.sfne r15, r0 /* hi-mem counter should still be 0 */ |
l.bf _dmmu_test_error |
l.nop |
|
706,10 → 613,10
l.sfne r7, r8 |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r18, 0x1 /* Check for lo mem mapping */ |
l.sfnei r14, 0x1 /* Check for lo mem mapping */ |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r19, 0x1 /* hi-mem counter should still be 0 */ |
l.sfnei r15, 0x1 /* hi-mem counter should still be 0 */ |
l.bf _dmmu_test_error |
l.nop |
|
719,10 → 626,10
l.sfne r7, r8 |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r18, 0x2 /* Check for lo mem mapping increment */ |
l.sfnei r14, 0x2 /* Check for lo mem mapping increment */ |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r19, 0x1 /* hi-mem counter should still be 1 */ |
l.sfnei r15, 0x1 /* hi-mem counter should still be 1 */ |
l.bf _dmmu_test_error |
l.nop |
|
729,10 → 636,10
l.addi r7, r7, 0x1111 /* Incremement value we're writing */ |
|
l.sw 4(r6), r7 /* Should cause DMMU miss, himem */ |
l.sfnei r18, 0x2 /* Check for lo mem mapping */ |
l.sfnei r14, 0x2 /* Check for lo mem mapping */ |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r19, 0x2 /* hi-mem counter should be 2 */ |
l.sfnei r15, 0x2 /* hi-mem counter should be 2 */ |
l.bf _dmmu_test_error |
l.nop |
|
741,10 → 648,10
l.sfne r7, r8 |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r18, 0x3 /* Check for lo mem mapping increment */ |
l.sfnei r14, 0x3 /* Check for lo mem mapping increment */ |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r19, 0x2 /* hi-mem counter should still be 2 */ |
l.sfnei r15, 0x2 /* hi-mem counter should still be 2 */ |
l.bf _dmmu_test_error |
l.nop |
|
777,10 → 684,10
l.sfne r7, r8 |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r18, 0xb /* Check for lo mem mapping increment to 11 */ |
l.sfnei r14, 0xb /* Check for lo mem mapping increment to 11 */ |
l.bf _dmmu_test_error |
l.nop |
l.sfnei r19, 0xa /* hi-mem counter should be 10 */ |
l.sfnei r15, 0xa /* hi-mem counter should be 10 */ |
l.bf _dmmu_test_error |
l.nop |
|
/Makefile.inc
29,8 → 29,6
#### #### |
###################################################################### |
|
DESIGN_NAME ?=orpsoc |
|
OR32_TOOL_PREFIX=or32-elf- |
|
OR32_LD=$(OR32_TOOL_PREFIX)ld |
46,11 → 44,17
# Special case for CPU drivers |
CPU_DRIVER ?=$(SW_ROOT)/drivers/or1200 |
|
# If BOARD_PATH is set, we'll first scan that path for which drivers they have |
DESIGN_NAME ?=orpsoc |
|
# If BOARD is set, we'll first scan that path for which drivers they have |
# and will override any locally named driver directories here. |
ifdef BOARD |
BOARD_PATH=$(SW_ROOT)/../boards/$(BOARD) |
#$(info BOARD is being used: $(BOARD_PATH)) |
|
ifeq ($(V), 1) |
$(info BOARD is set to : $(BOARD_PATH)) |
endif |
|
BOARD_SPECIFIC_DRIVERS=$(shell if [ -e \ |
$(BOARD_PATH)/sw/drivers ]; then \ |
ls $(BOARD_PATH)/sw/drivers; \ |
58,6 → 62,12
BOARD_SW_TESTS=$(shell if [ -e $(BOARD_PATH)/sw/tests ]; then\ |
ls $(BOARD_PATH)/sw/tests; \ |
fi) |
|
# Set RTL_VERILOG_INCLUDE_DIR |
RTL_VERILOG_INCLUDE_DIR=$(BOARD_PATH)/rtl/verilog/include |
#We don't actually want this |
#DESIGN_NAME ?=$(strip $(shell echo $(BOARD)| cut -d '/' -f 2)) |
|
endif |
|
COMMON_SW_DRIVERS=$(shell ls $(SW_ROOT)/drivers ) |
199,10 → 209,10
%.elf: %.S $(ELF_DEPENDS) $(SUPPORT_LIBS) |
$(Q)$(OR32_CC) $< $(ELF_DEPENDS) $(OR32_CFLAGS) $(OR32_LDFLAGS) -o $@ |
|
%.o: %.S |
%.o: %.S processed-verilog-headers |
$(Q)$(OR32_CC) $(OR32_CFLAGS) -c $< -o $@ |
|
%.o: %.c |
%.o: %.c processed-verilog-headers |
$(Q)$(OR32_CC) $(OR32_CFLAGS) -c $< -o $@ |
|
COMPILE_SRCS_BASENAMES=$(basename $(COMPILE_SRCS)) |
213,11 → 223,11
|
# Rule to make all necessary driver objects |
|
$(ORPSOC_LIB): $(PROCESSED_DEFINES) |
$(ORPSOC_LIB): |
$(Q)echo; echo "\t### Building software support library ###"; echo |
$(Q)$(MAKE) -C $(SW_ROOT)/lib liborpsoc.a |
|
$(VECTORS_OBJ): |
$(VECTORS_OBJ): |
$(Q)$(MAKE) -C $(CPU_DRIVER) crt0.o |
|
|
/drivers/ethmac/include/ethmac.h
64,7 → 64,11
uint mac_addr0; /* MAC Individual Address Register 0 */ |
uint mac_addr1; /* MAC Individual Address Register 1 */ |
uint hash_addr0; /* Hash Register 0 */ |
uint hash_addr1; /* Hash Register 1 */ |
uint hash_addr1; /* Hash Register 1 */ |
uint txctrl; /* Transmit control frame Register */ |
uint rxctrl; /* Rx control frame Register */ |
uint wbdbg; /* Wishbone state machine debug information */ |
|
} oeth_regs; |
|
/* Ethernet buffer descriptor */ |
/drivers/or1200/cache.S
0,0 → 1,114
#include "spr-defs.h" |
/* Cache init. To be called during init ONLY */ |
|
.global _cache_init |
.type _cache_init,@function |
|
_cache_init: |
/* Instruction cache enable */ |
/* Check if IC present and skip enabling otherwise */ |
l.mfspr r3,r0,SPR_UPR |
l.andi r4,r3,SPR_UPR_ICP |
l.sfeq r4,r0 |
l.bf .L8 |
l.nop |
|
/* Disable IC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_ICE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
|
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r3,r0,SPR_ICCFGR |
l.andi r4,r3,SPR_ICCFGR_CBS |
l.srli r5,r4,7 |
l.ori r6,r0,16 |
l.sll r14,r6,r5 |
|
/* Establish number of cache sets |
r7 contains number of cache sets |
r5 contains log(# of cache sets) |
*/ |
l.andi r4,r3,SPR_ICCFGR_NCS |
l.srli r5,r4,3 |
l.ori r6,r0,1 |
l.sll r7,r6,r5 |
|
/* Invalidate IC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r5 |
|
.L7: |
l.mtspr r0,r6,SPR_ICBIR |
l.sfne r6,r5 |
l.bf .L7 |
l.add r6,r6,r14 |
|
/* Enable IC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_ICE |
l.mtspr r0,r6,SPR_SR |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
|
.L8: |
/* Data cache enable */ |
/* Check if DC present and skip enabling otherwise */ |
l.mfspr r3,r0,SPR_UPR |
l.andi r4,r3,SPR_UPR_DCP |
l.sfeq r4,r0 |
l.bf .L10 |
l.nop |
/* Disable DC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_DCE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r3,r0,SPR_DCCFGR |
l.andi r4,r3,SPR_DCCFGR_CBS |
l.srli r5,r4,7 |
l.ori r6,r0,16 |
l.sll r14,r6,r5 |
/* Establish number of cache sets |
r7 contains number of cache sets |
r5 contains log(# of cache sets) |
*/ |
l.andi r4,r3,SPR_DCCFGR_NCS |
l.srli r5,r4,3 |
l.ori r6,r0,1 |
l.sll r7,r6,r5 |
/* Invalidate DC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r5 |
.L9: |
l.mtspr r0,r6,SPR_DCBIR |
l.sfne r6,r5 |
l.bf .L9 |
l.add r6,r6,r14 |
/* Enable DC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_DCE |
l.mtspr r0,r6,SPR_SR |
|
.L10: |
/* Return */ |
l.jr r9 |
l.nop |
/drivers/or1200/crt0.S
65,6 → 65,7
l.movhi r29, 0 |
l.movhi r30, 0 |
l.movhi r31, 0 |
|
/* Clear status register, set supervisor mode */ |
l.ori r1, r0, SPR_SR_SM |
l.mtspr r0, r1, SPR_SR |
196,125 → 197,18
|
ENTRY(_start) |
|
|
|
/* Instruction cache enable */ |
/* Check if IC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_ICP |
l.sfeq r26,r0 |
l.bf .L8 |
/* Cache initialisation */ |
l.jal _cache_init |
l.nop |
|
/* Disable IC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_ICE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
|
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_ICCFGR |
l.andi r26,r24,SPR_ICCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
|
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_ICCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
|
/* Invalidate IC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
|
.L7: |
l.mtspr r0,r6,SPR_ICBIR |
l.sfne r6,r5 |
l.bf .L7 |
l.add r6,r6,r14 |
|
/* Enable IC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_ICE |
l.mtspr r0,r6,SPR_SR |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
l.nop |
|
.L8: |
/* Data cache enable */ |
/* Check if DC present and skip enabling otherwise */ |
l.mfspr r24,r0,SPR_UPR |
l.andi r26,r24,SPR_UPR_DCP |
l.sfeq r26,r0 |
l.bf .L10 |
l.nop |
/* Disable DC */ |
l.mfspr r6,r0,SPR_SR |
l.addi r5,r0,-1 |
l.xori r5,r5,SPR_SR_DCE |
l.and r5,r6,r5 |
l.mtspr r0,r5,SPR_SR |
/* Establish cache block size |
If BS=0, 16; |
If BS=1, 32; |
r14 contain block size |
*/ |
l.mfspr r24,r0,SPR_DCCFGR |
l.andi r26,r24,SPR_DCCFGR_CBS |
l.srli r28,r26,7 |
l.ori r30,r0,16 |
l.sll r14,r30,r28 |
/* Establish number of cache sets |
r16 contains number of cache sets |
r28 contains log(# of cache sets) |
*/ |
l.andi r26,r24,SPR_DCCFGR_NCS |
l.srli r28,r26,3 |
l.ori r30,r0,1 |
l.sll r16,r30,r28 |
/* Invalidate DC */ |
l.addi r6,r0,0 |
l.sll r5,r14,r28 |
.L9: |
l.mtspr r0,r6,SPR_DCBIR |
l.sfne r6,r5 |
l.bf .L9 |
l.add r6,r6,r14 |
/* Enable DC */ |
l.mfspr r6,r0,SPR_SR |
l.ori r6,r6,SPR_SR_DCE |
l.mtspr r0,r6,SPR_SR |
|
.L10: |
|
/* Clear BSS */ |
LOAD_SYMBOL_2_GPR(r28, _bss_start) |
LOAD_SYMBOL_2_GPR(r30, _bss_end) |
LOAD_SYMBOL_2_GPR(r5, _bss_start) |
LOAD_SYMBOL_2_GPR(r6, _bss_end) |
1: |
l.sw (0)(r28), r0 |
l.sfltu r28, r30 |
l.sw (0)(r5), r0 |
l.sfltu r5, r6 |
l.bf 1b |
l.addi r28, r28, 4 |
|
/* Initialise UART in a C function */ |
/*l.jal _uart_init |
l.nop*/ |
l.addi r5, r5, 4 |
|
/* Jump to main program entry point (argc = argv = 0) */ |
CLEAR_GPR(r3) |
360,7 → 254,7
l.sw 0x70(r1), r30 |
l.sw 0x74(r1), r31 |
l.sw 0x78(r1), r32 |
|
|
l.jal default_exception_handler_c |
l.nop |
|
/drivers/or1200/int.c
25,37 → 25,37
} |
|
/* Add interrupt handler */ |
int int_add(unsigned long vect, void (* handler)(void *), void *arg) |
int int_add(unsigned long irq, void (* handler)(void *), void *arg) |
{ |
if(vect >= MAX_INT_HANDLERS) |
if(irq >= MAX_INT_HANDLERS) |
return -1; |
|
int_handlers[vect].handler = handler; |
int_handlers[vect].arg = arg; |
int_handlers[irq].handler = handler; |
int_handlers[irq].arg = arg; |
|
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << vect)); |
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << irq)); |
|
return 0; |
} |
|
/* Disable interrupt */ |
int int_disable(unsigned long vect) |
int int_disable(unsigned long irq) |
{ |
if(vect >= MAX_INT_HANDLERS) |
if(irq >= MAX_INT_HANDLERS) |
return -1; |
|
mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(0x00000001L << vect)); |
mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(0x00000001L << irq)); |
|
return 0; |
} |
|
/* Enable interrupt */ |
int int_enable(unsigned long vect) |
int int_enable(unsigned long irq) |
{ |
if(vect >= MAX_INT_HANDLERS) |
if(irq >= MAX_INT_HANDLERS) |
return -1; |
|
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << vect)); |
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << irq)); |
|
return 0; |
} |
71,7 → 71,12
while(i < 32) { |
if((picsr & (0x01L << i)) && (int_handlers[i].handler != 0)) { |
(*int_handlers[i].handler)(int_handlers[i].arg); |
mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(0x00000001L << i)); |
#ifdef OR1200_INT_CHECK_BIT_CLEARED |
// Ensure PICSR bit is cleared, incase it takes some time for the |
// IRQ line going low to propagate back to PIC |
while (mfspr(SPR_PICSR) & (0x00000001L << i)) |
#endif |
mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(0x00000001L << i)); |
} |
i++; |
} |
/drivers/or1200/link.ld
72,14 → 72,10
/* ensure there is enough room for stack */ |
.stack (NOLOAD): { |
. = ALIGN(4); |
sstack = . ; |
_sstack = . ; |
. = . + _min_stack ; |
. = . + _min_stack ; |
. = ALIGN(4); |
stack = . ; |
_stack = . ; |
estack = . ; |
_estack = . ; |
} > ram |
|
.stab 0 (NOLOAD) : |
/drivers/or1200/Makefile
1,7 → 1,7
SW_ROOT=../.. |
|
# Sources to go into the liborpsoc.a support library |
COMPILE_SRCS=exceptions.c int.c or1200-mmu.S or1200-utils.c |
COMPILE_SRCS=exceptions.c int.c or1200-mmu.S or1200-utils.c cache.S |
|
include $(SW_ROOT)/Makefile.inc |
|