URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or1k/tags/stable_0_2_0_rc3/or1ksim/peripheral
- from Rev 1648 to Rev 1765
- ↔ Reverse comparison
Rev 1648 → Rev 1765
/eth.c
0,0 → 1,919
/* ethernet.c -- Simulation of Ethernet MAC |
Copyright (C) 2001 by Erez Volk, erez@opencores.org |
Ivan Guzvinec, ivang@opencores.org |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
*/ |
|
#include <stdlib.h> |
#include <stdio.h> |
#include <string.h> |
#include <sys/types.h> |
#include <sys/stat.h> |
#include <fcntl.h> |
#include <sys/poll.h> |
#include <sys/time.h> |
#include <unistd.h> |
#include <errno.h> |
#include <netinet/in.h> |
|
#include "config.h" |
|
#ifdef HAVE_INTTYPES_H |
#include <inttypes.h> |
#endif |
|
#include "port.h" |
#include "arch.h" |
#include "config.h" |
#include "abstract.h" |
#include "ethernet_i.h" |
#include "dma.h" |
#include "sim-config.h" |
#include "fields.h" |
#include "crc32.h" |
#include "vapi.h" |
#include "pic.h" |
#include "sched.h" |
#include "debug.h" |
|
DEFAULT_DEBUG_CHANNEL(eth); |
|
/* simulator interface */ |
static void eth_vapi_read( unsigned long id, unsigned long data, void *dat); |
/* register interface */ |
static void eth_write32( oraddr_t addr, uint32_t value, void *dat ); |
static uint32_t eth_read32( oraddr_t addr, void *dat ); |
/* clock */ |
static void eth_controller_tx_clock( void * ); |
static void eth_controller_rx_clock( void * ); |
/* utility functions */ |
static ssize_t eth_read_rx_file( struct eth_device *, void *, size_t ); |
static void eth_skip_rx_file( struct eth_device *, off_t ); |
static void eth_rx_next_packet( struct eth_device * ); |
static void eth_write_tx_bd_num( struct eth_device *, unsigned long value ); |
/* ========================================================================= */ |
/* TX LOGIC */ |
/*---------------------------------------------------------------------------*/ |
|
/* |
* TX clock |
* Responsible for starting and finishing TX |
*/ |
void eth_controller_tx_clock( void *dat ) |
{ |
struct eth_device *eth = dat; |
int bAdvance = 1; |
#if HAVE_ETH_PHY |
struct sockaddr_ll sll; |
#endif /* HAVE_ETH_PHY */ |
long nwritten = 0; |
unsigned long read_word; |
|
switch (eth->tx.state) { |
case ETH_TXSTATE_IDLE: |
TRACE ("TX - entering state WAIT4BD (%ld)\n", eth->tx.bd_index); |
eth->tx.state = ETH_TXSTATE_WAIT4BD; |
break; |
case ETH_TXSTATE_WAIT4BD: |
/* Read buffer descriptor */ |
eth->tx.bd = eth->regs.bd_ram[eth->tx.bd_index]; |
eth->tx.bd_addr = eth->regs.bd_ram[eth->tx.bd_index + 1]; |
|
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, READY ) ) { |
/*****************/ |
/* initialize TX */ |
eth->tx.bytes_left = eth->tx.packet_length = GET_FIELD( eth->tx.bd, ETH_TX_BD, LENGTH ); |
eth->tx.bytes_sent = 0; |
|
/* Initialize error status bits */ |
CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, DEFER ); |
CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, COLLISION ); |
CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, RETRANSMIT ); |
CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, UNDERRUN ); |
CLEAR_FLAG( eth->tx.bd, ETH_TX_BD, NO_CARRIER ); |
SET_FIELD ( eth->tx.bd, ETH_TX_BD, RETRY, 0 ); |
|
/* Find out minimum length */ |
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, PAD ) || |
TEST_FLAG( eth->regs.moder, ETH_MODER, PAD ) ) |
eth->tx.minimum_length = GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MINFL ); |
else |
eth->tx.minimum_length = eth->tx.packet_length; |
|
/* Find out maximum length */ |
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, HUGEN ) ) |
eth->tx.maximum_length = eth->tx.packet_length; |
else |
eth->tx.maximum_length = GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MAXFL ); |
|
/* Do we need CRC on this packet? */ |
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, CRCEN ) || |
(TEST_FLAG( eth->tx.bd, ETH_TX_BD, CRC) && |
TEST_FLAG( eth->tx.bd, ETH_TX_BD, LAST)) ) |
eth->tx.add_crc = 1; |
else |
eth->tx.add_crc = 0; |
|
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, DLYCRCEN ) ) |
eth->tx.crc_dly = 1; |
else |
eth->tx.crc_dly = 0; |
/* XXX - For now we skip CRC calculation */ |
|
TRACE( "Ethernet: Starting TX of %lu bytes (min. %u, max. %u)\n", |
eth->tx.packet_length, eth->tx.minimum_length, |
eth->tx.maximum_length ); |
|
if (eth->rtx_type == ETH_RTX_FILE) { |
/* write packet length to file */ |
nwritten = write( eth->txfd, &(eth->tx.packet_length), sizeof(eth->tx.packet_length) ); |
} |
|
/************************************************/ |
/* start transmit with reading packet into FIFO */ |
TRACE ("TX - entering state READFIFO\n"); |
eth->tx.state = ETH_TXSTATE_READFIFO; |
} |
|
/* stay in this state if (TXEN && !READY) */ |
break; |
case ETH_TXSTATE_READFIFO: |
#if 1 |
if ( eth->tx.bytes_sent < eth->tx.packet_length ) { |
read_word = eval_direct32(eth->tx.bytes_sent + eth->tx.bd_addr, 0, 0); |
eth->tx_buff[eth->tx.bytes_sent] = (unsigned char)(read_word >> 24); |
eth->tx_buff[eth->tx.bytes_sent+1] = (unsigned char)(read_word >> 16); |
eth->tx_buff[eth->tx.bytes_sent+2] = (unsigned char)(read_word >> 8); |
eth->tx_buff[eth->tx.bytes_sent+3] = (unsigned char)(read_word); |
eth->tx.bytes_sent += 4; |
} |
#else |
if ( eth->tx.bytes_sent < eth->tx.packet_length ) { |
eth->tx_buff[eth->tx.bytes_sent] = eval_direct8(eth->tx.bytes_sent + eth->tx.bd_addr, 0, 0); |
eth->tx.bytes_sent += 1; |
} |
#endif |
else { |
TRACE ("TX - entering state TRANSMIT\n"); |
eth->tx.state = ETH_TXSTATE_TRANSMIT; |
} |
break; |
case ETH_TXSTATE_TRANSMIT: |
/* send packet */ |
switch (eth->rtx_type) { |
case ETH_RTX_FILE: |
nwritten = write( eth->txfd, eth->tx_buff, eth->tx.packet_length ); |
break; |
#if HAVE_ETH_PHY |
case ETH_RTX_SOCK: |
memset(&sll, 0, sizeof(sll)); |
sll.sll_ifindex = eth->ifr.ifr_ifindex; |
nwritten = sendto(eth->rtx_sock, eth->tx_buff, eth->tx.packet_length, 0, (struct sockaddr *)&sll, sizeof(sll)); |
#endif /* HAVE_ETH_PHY */ |
} |
|
/* set BD status */ |
if (nwritten == eth->tx.packet_length) { |
CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY); |
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXB); |
TRACE ("ETH_INT_SOURCE = %0lx\n", eth->regs.int_source); |
|
TRACE ("TX - entering state WAIT4BD\n"); |
eth->tx.state = ETH_TXSTATE_WAIT4BD; |
TRACE ("send (%ld)bytes OK\n", nwritten); |
} |
else { |
/* XXX - implement retry mechanism here! */ |
CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, READY); |
CLEAR_FLAG (eth->tx.bd, ETH_TX_BD, COLLISION); |
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, TXE); |
TRACE ("ETH_INT_SOURCE = %0lx\n", eth->regs.int_source); |
|
TRACE ("TX - entering state WAIT4BD\n"); |
eth->tx.state = ETH_TXSTATE_WAIT4BD; |
TRACE ("send FAILED!\n"); |
} |
|
eth->regs.bd_ram[eth->tx.bd_index] = eth->tx.bd; |
|
/* generate OK interrupt */ |
if ( TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, TXE_M) || |
TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, TXB_M) ) |
{ |
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, IRQ ) ) |
report_interrupt( eth->mac_int ); |
} |
|
/* advance to next BD */ |
if (bAdvance) { |
if ( TEST_FLAG( eth->tx.bd, ETH_TX_BD, WRAP ) || |
eth->tx.bd_index >= ETH_BD_COUNT ) |
eth->tx.bd_index = 0; |
else |
eth->tx.bd_index += 2; |
} |
|
break; |
} |
|
/* Reschedule */ |
SCHED_ADD( eth_controller_tx_clock, dat, 1 ); |
} |
/* ========================================================================= */ |
|
|
/* ========================================================================= */ |
/* RX LOGIC */ |
/*---------------------------------------------------------------------------*/ |
|
/* |
* RX clock |
* Responsible for starting and finishing RX |
*/ |
void eth_controller_rx_clock( void *dat ) |
{ |
struct eth_device *eth = dat; |
long nread; |
unsigned long send_word; |
|
|
switch (eth->rx.state) { |
case ETH_RXSTATE_IDLE: |
TRACE ("RX - entering state WAIT4BD (%ld)\n", eth->rx.bd_index); |
eth->rx.state = ETH_RXSTATE_WAIT4BD; |
break; |
|
case ETH_RXSTATE_WAIT4BD: |
eth->rx.bd = eth->regs.bd_ram[eth->rx.bd_index]; |
eth->rx.bd_addr = eth->regs.bd_ram[eth->rx.bd_index + 1]; |
|
if ( TEST_FLAG( eth->rx.bd, ETH_RX_BD, READY ) ) { |
/*****************/ |
/* Initialize RX */ |
CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, MISS ); |
CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, INVALID ); |
CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, DRIBBLE ); |
CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, UVERRUN ); |
CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, COLLISION ); |
CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, TOOBIG ); |
CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, TOOSHORT ); |
|
TRACE( "Ethernet: Starting RX\n" ); |
|
/* Setup file to read from */ |
if ( TEST_FLAG( eth->regs.moder, ETH_MODER, LOOPBCK ) ) { |
eth->rx.fd = eth->txfd; |
eth->rx.offset = &(eth->loopback_offset); |
} else { |
eth->rx.fd = eth->rxfd; |
eth->rx.offset = 0; |
} |
TRACE ("RX - entering state RECV\n"); |
eth->rx.state = ETH_RXSTATE_RECV; |
} |
else if (!TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN)) { |
TRACE ("RX - entering state IDLE\n"); |
eth->rx.state = ETH_RXSTATE_IDLE; |
} |
else { |
nread = recv(eth->rtx_sock, eth->rx_buff, ETH_MAXPL, /*MSG_PEEK | */MSG_DONTWAIT); |
if (nread > 0) { |
SET_FLAG (eth->regs.int_source, ETH_INT_SOURCE, BUSY); |
if ( TEST_FLAG(eth->regs.int_mask, ETH_INT_MASK, BUSY_M) ) |
report_interrupt(eth->mac_int); |
} |
} |
break; |
|
case ETH_RXSTATE_RECV: |
switch (eth->rtx_type) { |
case ETH_RTX_FILE: |
/* Read packet length */ |
if ( eth_read_rx_file( eth, &(eth->rx.packet_length), sizeof(eth->rx.packet_length) ) |
< sizeof(eth->rx.packet_length) ) { |
/* TODO: just do what real ethernet would do (some kind of error state) */ |
TRACE ("eth_start_rx(): File does not have a packet ready for RX (len = %ld)\n", eth->rx.packet_length ); |
sim_done(); |
break; |
} |
|
/* Packet must be big enough to hold a header */ |
if ( eth->rx.packet_length < ETHER_HDR_LEN ){ |
TRACE( "eth_start_rx(): Packet too small\n" ); |
eth_rx_next_packet( eth ); |
|
TRACE ("RX - entering state WAIT4BD\n"); |
eth->rx.state = ETH_RXSTATE_WAIT4BD; |
break; |
} |
|
eth->rx.bytes_read = 0; |
eth->rx.bytes_left = eth->rx.packet_length; |
|
/* for now Read entire packet into memory */ |
nread = eth_read_rx_file( eth, eth->rx_buff, eth->rx.bytes_left ); |
if ( nread < eth->rx.bytes_left ) { |
TRACE ("Read %ld from %ld. Error!\n", nread, eth->rx.bytes_left); |
eth->rx.error = 1; |
break; |
} |
|
eth->rx.packet_length = nread; |
eth->rx.bytes_left = nread; |
eth->rx.bytes_read = 0; |
|
TRACE ("RX - entering state WRITEFIFO\n"); |
eth->rx.state = ETH_RXSTATE_WRITEFIFO; |
|
break; |
|
case ETH_RTX_SOCK: |
nread = recv(eth->rtx_sock, eth->rx_buff, ETH_MAXPL, MSG_DONTWAIT); |
|
if (nread == 0) { |
TRACE("No data read\n"); |
break; |
} else if (nread < 0) { |
if ( errno != EAGAIN ) { |
TRACE ("recv() FAILED!\n"); |
break; |
} |
else |
break; |
} |
/* If not promiscouos mode, check the destination address */ |
if (!TEST_FLAG(eth->regs.moder, ETH_MODER, PRO)) { |
if (TEST_FLAG(eth->regs.moder, ETH_MODER, IAM) && (eth->rx_buff[0] & 1)) { |
/* Nothing for now */ |
} |
|
if (eth->mac_address[5] != eth->rx_buff[0] || |
eth->mac_address[4] != eth->rx_buff[1] || |
eth->mac_address[3] != eth->rx_buff[2] || |
eth->mac_address[2] != eth->rx_buff[3] || |
eth->mac_address[1] != eth->rx_buff[4] || |
eth->mac_address[0] != eth->rx_buff[5]) |
break; |
} |
|
eth->rx.packet_length = nread; |
eth->rx.bytes_left = nread; |
eth->rx.bytes_read = 0; |
|
TRACE ("RX - entering state WRITEFIFO\n"); |
eth->rx.state = ETH_RXSTATE_WRITEFIFO; |
|
break; |
case ETH_RTX_VAPI: |
break; |
} |
break; |
|
case ETH_RXSTATE_WRITEFIFO: |
#if 1 |
send_word = ((unsigned long)eth->rx_buff[eth->rx.bytes_read] << 24) | |
((unsigned long)eth->rx_buff[eth->rx.bytes_read+1] << 16) | |
((unsigned long)eth->rx_buff[eth->rx.bytes_read+2] << 8) | |
((unsigned long)eth->rx_buff[eth->rx.bytes_read+3] ); |
set_direct32( eth->rx.bd_addr + eth->rx.bytes_read, send_word, 0, 0); |
/* update counters */ |
TRACE ("Write %ld, left %ld - %08lXd\n", eth->rx.bytes_read, |
eth->rx.bytes_left, send_word); |
eth->rx.bytes_left -= 4; |
eth->rx.bytes_read += 4; |
#else |
set_direct8( eth->rx.bd_addr + eth->rx.bytes_read, eth->rx_buff[eth->rx.bytes_read], 0, 0); |
eth->rx.bytes_left -= 1; |
eth->rx.bytes_read += 1; |
#endif |
|
if ( eth->rx.bytes_left <= 0 ) { |
/* Write result to bd */ |
SET_FIELD( eth->rx.bd, ETH_RX_BD, LENGTH, eth->rx.packet_length ); |
CLEAR_FLAG( eth->rx.bd, ETH_RX_BD, READY); |
SET_FLAG( eth->regs.int_source, ETH_INT_SOURCE, RXB); |
TRACE ("ETH_INT_SOURCE = %0lx\n", eth->regs.int_source); |
|
if ( eth->rx.packet_length < (GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MINFL ) - 4) ) |
SET_FLAG( eth->rx.bd, ETH_RX_BD, TOOSHORT); |
if ( eth->rx.packet_length > GET_FIELD( eth->regs.packetlen, ETH_PACKETLEN, MAXFL ) ) |
SET_FLAG( eth->rx.bd, ETH_RX_BD, TOOBIG); |
|
eth->regs.bd_ram[eth->rx.bd_index] = eth->rx.bd; |
|
/* advance to next BD */ |
if ( TEST_FLAG( eth->rx.bd, ETH_RX_BD, WRAP ) || eth->rx.bd_index >= ETH_BD_COUNT ) |
eth->rx.bd_index = eth->regs.tx_bd_num << 1; |
else |
eth->rx.bd_index += 2; |
|
if ( ( TEST_FLAG( eth->regs.int_mask, ETH_INT_MASK, RXB_M ) ) && |
( TEST_FLAG( eth->rx.bd, ETH_RX_BD, IRQ ) ) ) { |
report_interrupt( eth->mac_int ); |
} |
|
/* ready to receive next packet */ |
TRACE ("RX - entering state IDLE\n"); |
eth->rx.state = ETH_RXSTATE_IDLE; |
} |
break; |
} |
|
/* Reschedule */ |
SCHED_ADD( eth_controller_rx_clock, dat, 1 ); |
} |
|
/* ========================================================================= */ |
/* Move to next RX BD */ |
void eth_rx_next_packet( struct eth_device *eth ) |
{ |
/* Skip any possible leftovers */ |
if ( eth->rx.bytes_left ) |
eth_skip_rx_file( eth, eth->rx.bytes_left ); |
} |
/* "Skip" bytes in RX file */ |
void eth_skip_rx_file( struct eth_device *eth, off_t count ) |
{ |
eth->rx.offset += count; |
} |
|
/* |
* Utility function to read from the ethernet RX file |
* This function moves the file pointer to the current place in the packet before reading |
*/ |
ssize_t eth_read_rx_file( struct eth_device *eth, void *buf, size_t count ) |
{ |
ssize_t result; |
|
if ( eth->rx.fd <= 0 ) { |
TRACE( "Ethernet: No RX file\n" ); |
return 0; |
} |
|
if ( eth->rx.offset ) |
if ( lseek( eth->rx.fd, *(eth->rx.offset), SEEK_SET ) == (off_t)-1 ) { |
TRACE( "Ethernet: Error seeking RX file\n" ); |
return 0; |
} |
|
result = read( eth->rx.fd, buf, count ); |
TRACE ("Ethernet: read result = %d \n", result); |
if ( eth->rx.offset && result >= 0 ) |
*(eth->rx.offset) += result; |
|
return result; |
} |
|
/* ========================================================================= */ |
|
/* |
Reset. Initializes all registers to default and places devices in |
memory address space. |
*/ |
void eth_reset(void *dat) |
{ |
struct eth_device *eth = dat; |
#if HAVE_ETH_PHY |
int j; |
struct sockaddr_ll sll; |
#endif /* HAVE_ETH_PHY */ |
|
if ( eth->baseaddr != 0 ) { |
switch (eth->rtx_type) { |
case ETH_RTX_FILE: |
/* (Re-)open TX/RX files */ |
if ( eth->rxfd > 0 ) |
close( eth->rxfd ); |
if ( eth->txfd > 0 ) |
close( eth->txfd ); |
eth->rxfd = eth->txfd = -1; |
|
if ( (eth->rxfd = open( eth->rxfile, O_RDONLY )) < 0 ) |
fprintf( stderr, "Cannot open Ethernet RX file \"%s\"\n", eth->rxfile ); |
if ( (eth->txfd = open( eth->txfile, |
O_RDWR | O_CREAT | O_APPEND |
|
#if defined(O_SYNC) /* BSD / Mac OS X manual doesn't know about O_SYNC */ |
| O_SYNC |
#endif |
, |
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH )) < 0 ) |
fprintf( stderr, "Cannot open Ethernet TX file \"%s\"\n", eth->txfile ); |
eth->loopback_offset = lseek( eth->txfd, 0, SEEK_END ); |
|
break; |
#if HAVE_ETH_PHY |
case ETH_RTX_SOCK: |
/* (Re-)open TX/RX sockets */ |
if (eth->rtx_sock != 0) |
break; |
|
TRACE ("RTX opening socket...\n"); |
eth->rtx_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); |
if (eth->rtx_sock == -1) { |
fprintf( stderr, "Cannot open rtx_sock.\n"); |
return; |
} |
|
/* get interface index number */ |
TRACE ("RTX getting interface...\n"); |
memset(&(eth->ifr), 0, sizeof(eth->ifr)); |
strncpy(eth->ifr.ifr_name, eth->sockif, IFNAMSIZ); |
if (ioctl(eth->rtx_sock, SIOCGIFINDEX, &(eth->ifr)) == -1) { |
fprintf( stderr, "SIOCGIFINDEX failed!\n"); |
return; |
} |
TRACE ("RTX Socket Interface : %d\n", eth->ifr.ifr_ifindex); |
|
/* Bind to interface... */ |
TRACE ("Binding to the interface ifindex=%d\n", eth->ifr.ifr_ifindex); |
memset(&sll, 0xff, sizeof(sll)); |
sll.sll_family = AF_PACKET; /* allways AF_PACKET */ |
sll.sll_protocol = htons(ETH_P_ALL); |
sll.sll_ifindex = eth->ifr.ifr_ifindex; |
if (bind(eth->rtx_sock, (struct sockaddr *)&sll, sizeof(sll)) == -1) { |
fprintf( stderr, "Error bind().\n"); |
return; |
} |
|
/* first, flush all received packets. */ |
TRACE ("Flush"); |
do { |
fd_set fds; |
struct timeval t; |
|
TRACE( "."); |
FD_ZERO(&fds); |
FD_SET(eth->rtx_sock, &fds); |
memset(&t, 0, sizeof(t)); |
j = select(FD_SETSIZE, &fds, NULL, NULL, &t); |
if (j > 0) |
recv(eth->rtx_sock, eth->rx_buff, j, 0); |
} while (j); |
TRACE ("\n"); |
|
break; |
#else /* HAVE_ETH_PHY */ |
case ETH_RTX_SOCK: |
fprintf (stderr, "Ethernet phy not enabled in this configuration. Configure with --enable-ethphy.\n"); |
exit (1); |
break; |
#endif /* HAVE_ETH_PHY */ |
} |
|
/* Set registers to default values */ |
memset( &(eth->regs), 0, sizeof(eth->regs) ); |
eth->regs.moder = 0x0000A000; |
eth->regs.ipgt = 0x00000012; |
eth->regs.ipgr1 = 0x0000000C; |
eth->regs.ipgr2 = 0x00000012; |
eth->regs.packetlen = 0x003C0600; |
eth->regs.collconf = 0x000F003F; |
eth->regs.miimoder = 0x00000064; |
eth->regs.tx_bd_num = 0x00000040; |
|
/* Initialize TX/RX status */ |
memset( &(eth->tx), 0, sizeof(eth->tx) ); |
memset( &(eth->rx), 0, sizeof(eth->rx) ); |
eth->rx.bd_index = eth->regs.tx_bd_num << 1; |
|
/* Initialize VAPI */ |
if (eth->base_vapi_id) { |
vapi_install_multi_handler( eth->base_vapi_id, ETH_NUM_VAPI_IDS, eth_vapi_read, dat ); |
} |
} |
} |
/* ========================================================================= */ |
|
|
/* |
Print register values on stdout |
*/ |
void eth_status( void *dat ) |
{ |
struct eth_device *eth = dat; |
|
PRINTF( "\nEthernet MAC at 0x%"PRIxADDR":\n", eth->baseaddr ); |
PRINTF( "MODER : 0x%08lX\n", eth->regs.moder ); |
PRINTF( "INT_SOURCE : 0x%08lX\n", eth->regs.int_source ); |
PRINTF( "INT_MASK : 0x%08lX\n", eth->regs.int_mask ); |
PRINTF( "IPGT : 0x%08lX\n", eth->regs.ipgt ); |
PRINTF( "IPGR1 : 0x%08lX\n", eth->regs.ipgr1 ); |
PRINTF( "IPGR2 : 0x%08lX\n", eth->regs.ipgr2 ); |
PRINTF( "PACKETLEN : 0x%08lX\n", eth->regs.packetlen ); |
PRINTF( "COLLCONF : 0x%08lX\n", eth->regs.collconf ); |
PRINTF( "TX_BD_NUM : 0x%08lX\n", eth->regs.tx_bd_num ); |
PRINTF( "CTRLMODER : 0x%08lX\n", eth->regs.controlmoder ); |
PRINTF( "MIIMODER : 0x%08lX\n", eth->regs.miimoder ); |
PRINTF( "MIICOMMAND : 0x%08lX\n", eth->regs.miicommand ); |
PRINTF( "MIIADDRESS : 0x%08lX\n", eth->regs.miiaddress ); |
PRINTF( "MIITX_DATA : 0x%08lX\n", eth->regs.miitx_data ); |
PRINTF( "MIIRX_DATA : 0x%08lX\n", eth->regs.miirx_data ); |
PRINTF( "MIISTATUS : 0x%08lX\n", eth->regs.miistatus ); |
PRINTF( "MAC Address : %02X:%02X:%02X:%02X:%02X:%02X\n", |
eth->mac_address[0], eth->mac_address[1], eth->mac_address[2], |
eth->mac_address[3], eth->mac_address[4], eth->mac_address[5] ); |
PRINTF( "HASH0 : 0x%08lX\n", eth->regs.hash0 ); |
PRINTF( "HASH1 : 0x%08lX\n", eth->regs.hash1 ); |
} |
/* ========================================================================= */ |
|
|
/* |
Read a register |
*/ |
uint32_t eth_read32( oraddr_t addr, void *dat ) |
{ |
struct eth_device *eth = dat; |
|
switch( addr ) { |
case ETH_MODER: return eth->regs.moder; |
case ETH_INT_SOURCE: return eth->regs.int_source; |
case ETH_INT_MASK: return eth->regs.int_mask; |
case ETH_IPGT: return eth->regs.ipgt; |
case ETH_IPGR1: return eth->regs.ipgr1; |
case ETH_IPGR2: return eth->regs.ipgr2; |
case ETH_PACKETLEN: return eth->regs.packetlen; |
case ETH_COLLCONF: return eth->regs.collconf; |
case ETH_TX_BD_NUM: return eth->regs.tx_bd_num; |
case ETH_CTRLMODER: return eth->regs.controlmoder; |
case ETH_MIIMODER: return eth->regs.miimoder; |
case ETH_MIICOMMAND: return eth->regs.miicommand; |
case ETH_MIIADDRESS: return eth->regs.miiaddress; |
case ETH_MIITX_DATA: return eth->regs.miitx_data; |
case ETH_MIIRX_DATA: return eth->regs.miirx_data; |
case ETH_MIISTATUS: return eth->regs.miistatus; |
case ETH_MAC_ADDR0: return (((unsigned long)eth->mac_address[3]) << 24) | |
(((unsigned long)eth->mac_address[2]) << 16) | |
(((unsigned long)eth->mac_address[1]) << 8) | |
(unsigned long)eth->mac_address[0]; |
case ETH_MAC_ADDR1: return (((unsigned long)eth->mac_address[5]) << 8) | |
(unsigned long)eth->mac_address[4]; |
case ETH_HASH0: return eth->regs.hash0; |
case ETH_HASH1: return eth->regs.hash1; |
/*case ETH_DMA_RX_TX: return eth_rx( eth );*/ |
} |
|
if ( (addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE) ) |
return eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4]; |
|
PRINTF( "eth_read32( 0x%"PRIxADDR" ): Illegal address\n", |
addr + eth->baseaddr ); |
return 0; |
} |
/* ========================================================================= */ |
|
|
/* |
Write a register |
*/ |
void eth_write32( oraddr_t addr, uint32_t value, void *dat ) |
{ |
struct eth_device *eth = dat; |
|
switch( addr ) { |
case ETH_MODER: |
|
if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN) && |
TEST_FLAG( value, ETH_MODER, RXEN) ) |
SCHED_ADD( eth_controller_rx_clock, dat, 1 ); |
else if ( !TEST_FLAG( value, ETH_MODER, RXEN) ) |
SCHED_FIND_REMOVE( eth_controller_rx_clock, dat); |
|
if ( !TEST_FLAG( eth->regs.moder, ETH_MODER, TXEN) && |
TEST_FLAG( value, ETH_MODER, TXEN) ) |
SCHED_ADD( eth_controller_tx_clock, dat, 1 ); |
else if ( !TEST_FLAG( value, ETH_MODER, TXEN) ) |
SCHED_FIND_REMOVE( eth_controller_tx_clock, dat); |
|
eth->regs.moder = value; |
|
if (TEST_FLAG(value, ETH_MODER, RST)) |
eth_reset( dat ); |
return; |
case ETH_INT_SOURCE: eth->regs.int_source &= ~value; return; |
case ETH_INT_MASK: eth->regs.int_mask = value; return; |
case ETH_IPGT: eth->regs.ipgt = value; return; |
case ETH_IPGR1: eth->regs.ipgr1 = value; return; |
case ETH_IPGR2: eth->regs.ipgr2 = value; return; |
case ETH_PACKETLEN: eth->regs.packetlen = value; return; |
case ETH_COLLCONF: eth->regs.collconf = value; return; |
case ETH_TX_BD_NUM: eth_write_tx_bd_num( eth, value ); return; |
case ETH_CTRLMODER: eth->regs.controlmoder = value; return; |
case ETH_MIIMODER: eth->regs.miimoder = value; return; |
case ETH_MIICOMMAND: eth->regs.miicommand = value; return; |
case ETH_MIIADDRESS: eth->regs.miiaddress = value; return; |
case ETH_MIITX_DATA: eth->regs.miitx_data = value; return; |
case ETH_MIIRX_DATA: eth->regs.miirx_data = value; return; |
case ETH_MIISTATUS: eth->regs.miistatus = value; return; |
case ETH_MAC_ADDR0: |
eth->mac_address[0] = value & 0xFF; |
eth->mac_address[1] = (value >> 8) & 0xFF; |
eth->mac_address[2] = (value >> 16) & 0xFF; |
eth->mac_address[3] = (value >> 24) & 0xFF; |
return; |
case ETH_MAC_ADDR1: |
eth->mac_address[4] = value & 0xFF; |
eth->mac_address[5] = (value >> 8) & 0xFF; |
return; |
case ETH_HASH0: eth->regs.hash0 = value; return; |
case ETH_HASH1: eth->regs.hash1 = value; return; |
|
/*case ETH_DMA_RX_TX: eth_tx( eth, value ); return;*/ |
} |
|
if ( (addr >= ETH_BD_BASE) && (addr < ETH_BD_BASE + ETH_BD_SPACE) ) { |
eth->regs.bd_ram[(addr - ETH_BD_BASE) / 4] = value; |
return; |
} |
|
PRINTF( "eth_write32( 0x%"PRIxADDR" ): Illegal address\n", |
addr + eth->baseaddr ); |
return; |
} |
/* ========================================================================= */ |
|
|
/* |
* VAPI connection to outside |
*/ |
static void eth_vapi_read (unsigned long id, unsigned long data, void *dat) |
{ |
unsigned long which; |
struct eth_device *eth = dat; |
|
which = id - eth->base_vapi_id; |
|
TRACE( "ETH: id %08lx, data %08lx\n", id, data ); |
|
if ( !eth ) { |
TRACE( "ETH: VAPI ID %08lx is not ours!\n", id ); |
return; |
} |
|
switch( which ) { |
case ETH_VAPI_DATA: |
break; |
case ETH_VAPI_CTRL: |
break; |
} |
} |
/* ========================================================================= */ |
|
|
/* When TX_BD_NUM is written, also reset current RX BD index */ |
void eth_write_tx_bd_num( struct eth_device *eth, unsigned long value ) |
{ |
eth->regs.tx_bd_num = value & 0xFF; |
eth->rx.bd_index = eth->regs.tx_bd_num << 1; |
} |
|
/* ========================================================================= */ |
|
/*-----------------------------------------------[ Ethernet configuration ]---*/ |
void eth_baseaddr(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
eth->baseaddr = val.addr_val; |
} |
|
void eth_dma(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
eth->dma = val.addr_val; |
} |
|
void eth_rtx_type(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
eth->rtx_type = val.int_val; |
} |
|
void eth_rx_channel(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
eth->rx_channel = val.int_val; |
} |
|
void eth_tx_channel(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
eth->tx_channel = val.int_val; |
} |
|
void eth_rxfile(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
if(!(eth->rxfile = strdup(val.str_val))) { |
fprintf(stderr, "Peripheral Ethernet: Run out of memory\n"); |
exit(-1); |
} |
} |
|
void eth_txfile(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
if(!(eth->txfile = strdup(val.str_val))) { |
fprintf(stderr, "Peripheral Ethernet: Run out of memory\n"); |
exit(-1); |
} |
} |
|
void eth_sockif(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
if(!(eth->sockif = strdup(val.str_val))) { |
fprintf(stderr, "Peripheral Ethernet: Run out of memory\n"); |
exit(-1); |
} |
} |
|
void eth_irq(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
eth->mac_int = val.int_val; |
} |
|
void eth_vapi_id(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
eth->base_vapi_id = val.int_val; |
} |
|
void eth_enabled(union param_val val, void *dat) |
{ |
struct eth_device *eth = dat; |
eth->enabled = val.int_val; |
} |
|
void *eth_sec_start(void) |
{ |
struct eth_device *new = malloc(sizeof(struct eth_device)); |
|
if(!new) { |
fprintf(stderr, "Peripheral Eth: Run out of memory\n"); |
exit(-1); |
} |
|
memset(new, 0, sizeof(struct eth_device)); |
new->enabled = 1; |
|
return new; |
} |
|
void eth_sec_end(void *dat) |
{ |
struct eth_device *eth = dat; |
struct mem_ops ops; |
|
if(!eth->enabled) { |
free(dat); |
return; |
} |
|
memset(&ops, 0, sizeof(struct mem_ops)); |
|
ops.readfunc32 = eth_read32; |
ops.writefunc32 = eth_write32; |
ops.read_dat32 = dat; |
ops.write_dat32 = dat; |
|
/* FIXME: Correct delay? */ |
ops.delayr = 2; |
ops.delayw = 2; |
reg_mem_area( eth->baseaddr, ETH_ADDR_SPACE, 0, &ops ); |
reg_sim_stat( eth_status, dat ); |
reg_sim_reset( eth_reset, dat ); |
} |
|
void reg_ethernet_sec(void) |
{ |
struct config_section *sec = reg_config_sec("ethernet", eth_sec_start, eth_sec_end); |
|
reg_config_param(sec, "irq", paramt_int, eth_irq); |
reg_config_param(sec, "enabled", paramt_int, eth_enabled); |
reg_config_param(sec, "baseaddr", paramt_addr, eth_baseaddr); |
reg_config_param(sec, "dma", paramt_int, eth_dma); |
reg_config_param(sec, "rtx_type", paramt_int, eth_rtx_type); |
reg_config_param(sec, "rx_channel", paramt_int, eth_rx_channel); |
reg_config_param(sec, "tx_channel", paramt_int, eth_tx_channel); |
reg_config_param(sec, "rxfile", paramt_str, eth_rxfile); |
reg_config_param(sec, "txfile", paramt_str, eth_txfile); |
reg_config_param(sec, "sockif", paramt_str, eth_sockif); |
reg_config_param(sec, "vapi_id", paramt_int, eth_vapi_id); |
} |
/memory.c
0,0 → 1,375
/* memory.c -- Generic memory model |
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
|
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#include <stdio.h> |
#include <time.h> |
#include <string.h> |
|
#include "config.h" |
|
#ifdef HAVE_INTTYPES_H |
#include <inttypes.h> |
#endif |
|
#include "port.h" |
#include "arch.h" |
#include "abstract.h" |
#include "sim-config.h" |
|
struct mem_config { |
int ce; /* Which ce this memory is associated with */ |
int mc; /* Which mc this memory is connected to */ |
oraddr_t baseaddr; /* Start address of the memory */ |
unsigned int size; /* Memory size */ |
char *name; /* Memory type string */ |
char *log; /* Memory log filename */ |
int delayr; /* Read cycles */ |
int delayw; /* Write cycles */ |
|
void *mem; /* malloced memory for this memory */ |
|
int pattern; /* A user specified memory initialization |
* pattern */ |
int random_seed; /* Initialize the memory with random values, |
* starting with seed */ |
enum { |
MT_UNKNOWN, |
MT_PATTERN, |
MT_RANDOM |
} type; |
}; |
|
uint32_t simmem_read32(oraddr_t addr, void *dat) |
{ |
return *(uint32_t *)(dat + addr); |
} |
|
uint16_t simmem_read16(oraddr_t addr, void *dat) |
{ |
#ifdef WORDS_BIGENDIAN |
return *(uint16_t *)(dat + addr); |
#else |
return *(uint16_t *)(dat + (addr ^ 2)); |
#endif |
} |
|
uint8_t simmem_read8(oraddr_t addr, void *dat) |
{ |
#ifdef WORDS_BIGENDIAN |
return *(uint8_t *)(dat + addr); |
#else |
return *(uint8_t *)(dat + ((addr & ~ADDR_C(3)) | (3 - (addr & 3)))); |
#endif |
} |
|
void simmem_write32(oraddr_t addr, uint32_t value, void *dat) |
{ |
*(uint32_t *)(dat + addr) = value; |
} |
|
void simmem_write16(oraddr_t addr, uint16_t value, void *dat) |
{ |
#ifdef WORDS_BIGENDIAN |
*(uint16_t *)(dat + addr) = value; |
#else |
*(uint16_t *)(dat + (addr ^ 2)) = value; |
#endif |
} |
|
void simmem_write8(oraddr_t addr, uint8_t value, void *dat) |
{ |
#ifdef WORDS_BIGENDIAN |
*(uint8_t *)(dat + addr) = value; |
#else |
*(uint8_t *)(dat + ((addr & ~ADDR_C(3)) | (3 - (addr & 3)))) = value; |
#endif |
} |
|
uint32_t simmem_read_zero32(oraddr_t addr, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 32-bit memory read from non-read memory area 0x%" |
PRIxADDR".\n", addr); |
return 0; |
} |
|
uint16_t simmem_read_zero16(oraddr_t addr, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 16-bit memory read from non-read memory area 0x%" |
PRIxADDR".\n", addr); |
return 0; |
} |
|
uint8_t simmem_read_zero8(oraddr_t addr, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 8-bit memory read from non-read memory area 0x%" |
PRIxADDR".\n", addr); |
return 0; |
} |
|
void simmem_write_null32(oraddr_t addr, uint32_t value, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 32-bit memory write to 0x%"PRIxADDR", non-write " |
"memory area (value 0x%08"PRIx32").\n", addr, value); |
} |
|
void simmem_write_null16(oraddr_t addr, uint16_t value, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 16-bit memory write to 0x%"PRIxADDR", non-write " |
"memory area (value 0x%08"PRIx32").\n", addr, value); |
} |
|
void simmem_write_null8(oraddr_t addr, uint8_t value, void *dat) |
{ |
if (config.sim.verbose) |
fprintf (stderr, "WARNING: 8-bit memory write to 0x%"PRIxADDR", non-write " |
"memory area (value 0x%08"PRIx32").\n", addr, value); |
} |
|
void mem_reset(void *dat) |
{ |
struct mem_config *mem = dat; |
int seed; |
int i; |
uint8_t *mem_area = mem->mem; |
|
/* Initialize memory */ |
switch(mem->type) { |
case MT_RANDOM: |
if (mem->random_seed == -1) { |
seed = time(NULL); |
/* Print out the seed just in case we ever need to debug */ |
PRINTF("Seeding random generator with value %d\n", seed); |
} else |
seed = mem->random_seed; |
srandom(seed); |
|
for(i = 0; i < mem->size; i++, mem_area++) |
*mem_area = random() & 0xFF; |
break; |
case MT_PATTERN: |
for(i = 0; i < mem->size; i++, mem_area++) |
*mem_area = mem->pattern; |
break; |
case MT_UNKNOWN: |
break; |
default: |
fprintf(stderr, "Invalid memory configuration type.\n"); |
exit(1); |
} |
} |
|
/*-------------------------------------------------[ Memory configuration ]---*/ |
void memory_random_seed(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->random_seed = val.int_val; |
} |
|
void memory_pattern(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->pattern = val.int_val; |
} |
|
void memory_type(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
if(!strcmp(val.str_val, "unknown")) |
mem->type = MT_UNKNOWN; |
else if(!strcmp (val.str_val, "random")) |
mem->type = MT_RANDOM; |
else if(!strcmp (val.str_val, "pattern")) |
mem->type = MT_PATTERN; |
else if(!strcmp (val.str_val, "zero")) { |
mem->type = MT_PATTERN; |
mem->pattern = 0; |
} else { |
char tmp[200]; |
sprintf (tmp, "invalid memory type '%s'.\n", val.str_val); |
CONFIG_ERROR(tmp); |
} |
} |
|
void memory_ce(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->ce = val.int_val; |
} |
|
void memory_mc(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->mc = val.int_val; |
} |
|
void memory_baseaddr(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->baseaddr = val.addr_val; |
} |
|
void memory_size(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->size = val.int_val; |
} |
|
/* FIXME: Check use */ |
void memory_name(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->name = strdup(val.str_val); |
} |
|
void memory_log(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->log = strdup(val.str_val); |
} |
|
void memory_delayr(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->delayr = val.int_val; |
} |
|
void memory_delayw(union param_val val, void *dat) |
{ |
struct mem_config *mem = dat; |
mem->delayw = val.int_val; |
} |
|
void *memory_sec_start(void) |
{ |
struct mem_config *mem = malloc(sizeof(struct mem_config)); |
|
if(!mem) { |
fprintf(stderr, "Memory Peripheral: Run out of memory\n"); |
exit(-1); |
} |
mem->size = 0; |
mem->log = NULL; |
mem->name = NULL; |
mem->delayr = 1; |
mem->delayw = 1; |
mem->random_seed = -1; |
mem->ce = -1; |
mem->mc = 0; |
|
return mem; |
} |
|
void memory_sec_end(void *dat) |
{ |
struct mem_config *mem = dat; |
struct dev_memarea *mema; |
|
struct mem_ops ops; |
|
if(!mem->size) { |
free(dat); |
return; |
} |
|
/* Round up to the next 32-bit boundry */ |
if(mem->size & 3) { |
mem->size &= ~3; |
mem->size += 4; |
} |
|
if(!(mem->mem = malloc(mem->size))) { |
fprintf(stderr, "Unable to allocate memory at %"PRIxADDR", length %i\n", |
mem->baseaddr, mem->size); |
exit(-1); |
} |
|
if(mem->delayr > 0) { |
ops.readfunc32 = simmem_read32; |
ops.readfunc16 = simmem_read16; |
ops.readfunc8 = simmem_read8; |
} else { |
ops.readfunc32 = simmem_read_zero32; |
ops.readfunc16 = simmem_read_zero16; |
ops.readfunc8 = simmem_read_zero8; |
} |
|
if(mem->delayw > 0) { |
ops.writefunc32 = simmem_write32; |
ops.writefunc16 = simmem_write16; |
ops.writefunc8 = simmem_write8; |
} else { |
ops.writefunc32 = simmem_write_null32; |
ops.writefunc16 = simmem_write_null16; |
ops.writefunc8 = simmem_write_null8; |
} |
|
ops.writeprog8 = simmem_write8; |
ops.writeprog32 = simmem_write32; |
ops.writeprog8_dat = mem->mem; |
ops.writeprog32_dat = mem->mem; |
|
ops.read_dat32 = mem->mem; |
ops.read_dat16 = mem->mem; |
ops.read_dat8 = mem->mem; |
|
ops.write_dat32 = mem->mem; |
ops.write_dat16 = mem->mem; |
ops.write_dat8 = mem->mem; |
|
ops.delayr = mem->delayr; |
ops.delayw = mem->delayw; |
|
ops.log = mem->log; |
|
mema = reg_mem_area(mem->baseaddr, mem->size, 0, &ops); |
|
/* Set valid */ |
/* FIXME: Should this be done during reset? */ |
set_mem_valid(mema, 1); |
|
if(mem->ce >= 0) |
mc_reg_mem_area(mema, mem->ce, mem->mc); |
|
reg_sim_reset(mem_reset, dat); |
} |
|
void reg_memory_sec(void) |
{ |
struct config_section *sec = reg_config_sec("memory", memory_sec_start, |
memory_sec_end); |
|
reg_config_param(sec, "random_seed", paramt_int, memory_random_seed); |
reg_config_param(sec, "pattern", paramt_int, memory_pattern); |
reg_config_param(sec, "type", paramt_word, memory_type); |
reg_config_param(sec, "ce", paramt_int, memory_ce); |
reg_config_param(sec, "mc", paramt_int, memory_mc); |
reg_config_param(sec, "baseaddr", paramt_addr, memory_baseaddr); |
reg_config_param(sec, "size", paramt_int, memory_size); |
reg_config_param(sec, "name", paramt_str, memory_name); |
reg_config_param(sec, "log", paramt_str, memory_log); |
reg_config_param(sec, "delayr", paramt_int, memory_delayr); |
reg_config_param(sec, "delayw", paramt_int, memory_delayw); |
} |
|
/Makefile.in
0,0 → 1,560
# Makefile.in generated by automake 1.9.5 from Makefile.am. |
# @configure_input@ |
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
# 2003, 2004, 2005 Free Software Foundation, Inc. |
# This Makefile.in is free software; the Free Software Foundation |
# gives unlimited permission to copy and/or distribute it, |
# with or without modifications, as long as this notice is preserved. |
|
# This program is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without |
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
# PARTICULAR PURPOSE. |
|
@SET_MAKE@ |
|
# Makefile -- Makefile for peripherals simulation |
# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org |
# |
# This file is part of OpenRISC 1000 Architectural Simulator. |
# |
# This program is free software; you can redistribute it and/or modify |
# it under the terms of the GNU General Public License as published by |
# the Free Software Foundation; either version 2 of the License, or |
# (at your option) any later version. |
# |
# This program 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 General Public License for more details. |
# |
# You should have received a copy of the GNU General Public License |
# along with this program; if not, write to the Free Software |
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
# |
|
SOURCES = $(libperipheral_a_SOURCES) |
|
srcdir = @srcdir@ |
top_srcdir = @top_srcdir@ |
VPATH = @srcdir@ |
pkgdatadir = $(datadir)/@PACKAGE@ |
pkglibdir = $(libdir)/@PACKAGE@ |
pkgincludedir = $(includedir)/@PACKAGE@ |
top_builddir = .. |
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd |
INSTALL = @INSTALL@ |
install_sh_DATA = $(install_sh) -c -m 644 |
install_sh_PROGRAM = $(install_sh) -c |
install_sh_SCRIPT = $(install_sh) -c |
INSTALL_HEADER = $(INSTALL_DATA) |
transform = $(program_transform_name) |
NORMAL_INSTALL = : |
PRE_INSTALL = : |
POST_INSTALL = : |
NORMAL_UNINSTALL = : |
PRE_UNINSTALL = : |
POST_UNINSTALL = : |
build_triplet = @build@ |
host_triplet = @host@ |
target_triplet = @target@ |
subdir = peripheral |
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in |
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 |
am__aclocal_m4_deps = $(top_srcdir)/configure.in |
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ |
$(ACLOCAL_M4) |
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs |
CONFIG_HEADER = $(top_builddir)/config.h |
CONFIG_CLEAN_FILES = |
LIBRARIES = $(noinst_LIBRARIES) |
libperipheral_a_AR = $(AR) $(ARFLAGS) |
libperipheral_a_LIBADD = |
am_libperipheral_a_OBJECTS = 16450.$(OBJEXT) dma.$(OBJEXT) \ |
mc.$(OBJEXT) eth.$(OBJEXT) crc32.$(OBJEXT) gpio.$(OBJEXT) \ |
vga.$(OBJEXT) fb.$(OBJEXT) ps2kbd.$(OBJEXT) atahost.$(OBJEXT) \ |
atadevice.$(OBJEXT) atadevice_cmdi.$(OBJEXT) memory.$(OBJEXT) |
libperipheral_a_OBJECTS = $(am_libperipheral_a_OBJECTS) |
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) |
depcomp = $(SHELL) $(top_srcdir)/depcomp |
am__depfiles_maybe = depfiles |
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ |
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) |
CCLD = $(CC) |
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ |
SOURCES = $(libperipheral_a_SOURCES) |
DIST_SOURCES = $(libperipheral_a_SOURCES) |
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ |
html-recursive info-recursive install-data-recursive \ |
install-exec-recursive install-info-recursive \ |
install-recursive installcheck-recursive installdirs-recursive \ |
pdf-recursive ps-recursive uninstall-info-recursive \ |
uninstall-recursive |
ETAGS = etags |
CTAGS = ctags |
DIST_SUBDIRS = $(SUBDIRS) |
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
ACLOCAL = @ACLOCAL@ |
AMDEP_FALSE = @AMDEP_FALSE@ |
AMDEP_TRUE = @AMDEP_TRUE@ |
AMTAR = @AMTAR@ |
AR = @AR@ |
ARFLAGS = @ARFLAGS@ |
AUTOCONF = @AUTOCONF@ |
AUTOHEADER = @AUTOHEADER@ |
AUTOMAKE = @AUTOMAKE@ |
AWK = @AWK@ |
BUILD_DIR = @BUILD_DIR@ |
CC = @CC@ |
CCDEPMODE = @CCDEPMODE@ |
CFLAGS = @CFLAGS@ |
CPP = @CPP@ |
CPPFLAGS = @CPPFLAGS@ |
CPU_ARCH = @CPU_ARCH@ |
CYGPATH_W = @CYGPATH_W@ |
DEFS = @DEFS@ |
DEPDIR = @DEPDIR@ |
DYNAMIC_EXECUTION_FALSE = @DYNAMIC_EXECUTION_FALSE@ |
DYNAMIC_EXECUTION_TRUE = @DYNAMIC_EXECUTION_TRUE@ |
ECHO_C = @ECHO_C@ |
ECHO_N = @ECHO_N@ |
ECHO_T = @ECHO_T@ |
EGREP = @EGREP@ |
EXEEXT = @EXEEXT@ |
GENERATE_NEEDED_FALSE = @GENERATE_NEEDED_FALSE@ |
GENERATE_NEEDED_TRUE = @GENERATE_NEEDED_TRUE@ |
INCLUDES = @INCLUDES@ |
INSTALL_DATA = @INSTALL_DATA@ |
INSTALL_PROGRAM = @INSTALL_PROGRAM@ |
INSTALL_SCRIPT = @INSTALL_SCRIPT@ |
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ |
LDFLAGS = @LDFLAGS@ |
LIBOBJS = @LIBOBJS@ |
LIBS = @LIBS@ |
LOCAL_CFLAGS = @LOCAL_CFLAGS@ |
LOCAL_DEFS = @LOCAL_DEFS@ |
LOCAL_LDFLAGS = @LOCAL_LDFLAGS@ |
LTLIBOBJS = @LTLIBOBJS@ |
MAKEINFO = @MAKEINFO@ |
MAKE_SHELL = @MAKE_SHELL@ |
OBJEXT = @OBJEXT@ |
PACKAGE = @PACKAGE@ |
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ |
PACKAGE_NAME = @PACKAGE_NAME@ |
PACKAGE_STRING = @PACKAGE_STRING@ |
PACKAGE_TARNAME = @PACKAGE_TARNAME@ |
PACKAGE_VERSION = @PACKAGE_VERSION@ |
PATH_SEPARATOR = @PATH_SEPARATOR@ |
RANLIB = @RANLIB@ |
SET_MAKE = @SET_MAKE@ |
SHELL = @SHELL@ |
STRIP = @STRIP@ |
SUMVERSION = @SUMVERSION@ |
TERMCAP_LIB = @TERMCAP_LIB@ |
VERSION = @VERSION@ |
ac_ct_CC = @ac_ct_CC@ |
ac_ct_RANLIB = @ac_ct_RANLIB@ |
ac_ct_STRIP = @ac_ct_STRIP@ |
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ |
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ |
am__include = @am__include@ |
am__leading_dot = @am__leading_dot@ |
am__quote = @am__quote@ |
am__tar = @am__tar@ |
am__untar = @am__untar@ |
bindir = @bindir@ |
build = @build@ |
build_alias = @build_alias@ |
build_cpu = @build_cpu@ |
build_os = @build_os@ |
build_vendor = @build_vendor@ |
datadir = @datadir@ |
exec_prefix = @exec_prefix@ |
host = @host@ |
host_alias = @host_alias@ |
host_cpu = @host_cpu@ |
host_os = @host_os@ |
host_vendor = @host_vendor@ |
includedir = @includedir@ |
infodir = @infodir@ |
install_sh = @install_sh@ |
libdir = @libdir@ |
libexecdir = @libexecdir@ |
localstatedir = @localstatedir@ |
mandir = @mandir@ |
mkdir_p = @mkdir_p@ |
oldincludedir = @oldincludedir@ |
prefix = @prefix@ |
program_transform_name = @program_transform_name@ |
sbindir = @sbindir@ |
sharedstatedir = @sharedstatedir@ |
sysconfdir = @sysconfdir@ |
target = @target@ |
target_alias = @target_alias@ |
target_cpu = @target_cpu@ |
target_os = @target_os@ |
target_vendor = @target_vendor@ |
SUBDIRS = channels |
noinst_LIBRARIES = libperipheral.a |
libperipheral_a_SOURCES = \ |
16450.c \ |
dma.c \ |
mc.c \ |
eth.c \ |
crc32.c \ |
gpio.c \ |
vga.c \ |
fb.c \ |
ps2kbd.c \ |
atahost.c \ |
atadevice.c \ |
atadevice_cmdi.c \ |
memory.c |
|
all: all-recursive |
|
.SUFFIXES: |
.SUFFIXES: .c .o .obj |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) |
@for dep in $?; do \ |
case '$(am__configure_deps)' in \ |
*$$dep*) \ |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ |
&& exit 0; \ |
exit 1;; \ |
esac; \ |
done; \ |
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu peripheral/Makefile'; \ |
cd $(top_srcdir) && \ |
$(AUTOMAKE) --gnu peripheral/Makefile |
.PRECIOUS: Makefile |
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status |
@case '$?' in \ |
*config.status*) \ |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ |
*) \ |
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ |
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ |
esac; |
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh |
|
$(top_srcdir)/configure: $(am__configure_deps) |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh |
$(ACLOCAL_M4): $(am__aclocal_m4_deps) |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh |
|
clean-noinstLIBRARIES: |
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) |
libperipheral.a: $(libperipheral_a_OBJECTS) $(libperipheral_a_DEPENDENCIES) |
-rm -f libperipheral.a |
$(libperipheral_a_AR) libperipheral.a $(libperipheral_a_OBJECTS) $(libperipheral_a_LIBADD) |
$(RANLIB) libperipheral.a |
|
mostlyclean-compile: |
-rm -f *.$(OBJEXT) |
|
distclean-compile: |
-rm -f *.tab.c |
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/16450.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atadevice.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atadevice_cmdi.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/atahost.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc32.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dma.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eth.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fb.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpio.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mc.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memory.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ps2kbd.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga.Po@am__quote@ |
|
.c.o: |
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ |
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCC_FALSE@ $(COMPILE) -c $< |
|
.c.obj: |
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ |
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` |
uninstall-info-am: |
|
# This directory's subdirectories are mostly independent; you can cd |
# into them and run `make' without going through this Makefile. |
# To change the values of `make' variables: instead of editing Makefiles, |
# (1) if the variable is set in `config.status', edit `config.status' |
# (which will cause the Makefiles to be regenerated when you run `make'); |
# (2) otherwise, pass the desired values on the `make' command line. |
$(RECURSIVE_TARGETS): |
@failcom='exit 1'; \ |
for f in x $$MAKEFLAGS; do \ |
case $$f in \ |
*=* | --[!k]*);; \ |
*k*) failcom='fail=yes';; \ |
esac; \ |
done; \ |
dot_seen=no; \ |
target=`echo $@ | sed s/-recursive//`; \ |
list='$(SUBDIRS)'; for subdir in $$list; do \ |
echo "Making $$target in $$subdir"; \ |
if test "$$subdir" = "."; then \ |
dot_seen=yes; \ |
local_target="$$target-am"; \ |
else \ |
local_target="$$target"; \ |
fi; \ |
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ |
|| eval $$failcom; \ |
done; \ |
if test "$$dot_seen" = "no"; then \ |
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ |
fi; test -z "$$fail" |
|
mostlyclean-recursive clean-recursive distclean-recursive \ |
maintainer-clean-recursive: |
@failcom='exit 1'; \ |
for f in x $$MAKEFLAGS; do \ |
case $$f in \ |
*=* | --[!k]*);; \ |
*k*) failcom='fail=yes';; \ |
esac; \ |
done; \ |
dot_seen=no; \ |
case "$@" in \ |
distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ |
*) list='$(SUBDIRS)' ;; \ |
esac; \ |
rev=''; for subdir in $$list; do \ |
if test "$$subdir" = "."; then :; else \ |
rev="$$subdir $$rev"; \ |
fi; \ |
done; \ |
rev="$$rev ."; \ |
target=`echo $@ | sed s/-recursive//`; \ |
for subdir in $$rev; do \ |
echo "Making $$target in $$subdir"; \ |
if test "$$subdir" = "."; then \ |
local_target="$$target-am"; \ |
else \ |
local_target="$$target"; \ |
fi; \ |
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ |
|| eval $$failcom; \ |
done && test -z "$$fail" |
tags-recursive: |
list='$(SUBDIRS)'; for subdir in $$list; do \ |
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ |
done |
ctags-recursive: |
list='$(SUBDIRS)'; for subdir in $$list; do \ |
test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \ |
done |
|
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) |
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
unique=`for i in $$list; do \ |
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
done | \ |
$(AWK) ' { files[$$0] = 1; } \ |
END { for (i in files) print i; }'`; \ |
mkid -fID $$unique |
tags: TAGS |
|
TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ |
$(TAGS_FILES) $(LISP) |
tags=; \ |
here=`pwd`; \ |
if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ |
include_option=--etags-include; \ |
empty_fix=.; \ |
else \ |
include_option=--include; \ |
empty_fix=; \ |
fi; \ |
list='$(SUBDIRS)'; for subdir in $$list; do \ |
if test "$$subdir" = .; then :; else \ |
test ! -f $$subdir/TAGS || \ |
tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \ |
fi; \ |
done; \ |
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
unique=`for i in $$list; do \ |
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
done | \ |
$(AWK) ' { files[$$0] = 1; } \ |
END { for (i in files) print i; }'`; \ |
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ |
test -n "$$unique" || unique=$$empty_fix; \ |
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ |
$$tags $$unique; \ |
fi |
ctags: CTAGS |
CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ |
$(TAGS_FILES) $(LISP) |
tags=; \ |
here=`pwd`; \ |
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
unique=`for i in $$list; do \ |
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
done | \ |
$(AWK) ' { files[$$0] = 1; } \ |
END { for (i in files) print i; }'`; \ |
test -z "$(CTAGS_ARGS)$$tags$$unique" \ |
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ |
$$tags $$unique |
|
GTAGS: |
here=`$(am__cd) $(top_builddir) && pwd` \ |
&& cd $(top_srcdir) \ |
&& gtags -i $(GTAGS_ARGS) $$here |
|
distclean-tags: |
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags |
|
distdir: $(DISTFILES) |
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ |
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ |
list='$(DISTFILES)'; for file in $$list; do \ |
case $$file in \ |
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ |
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ |
esac; \ |
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ |
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ |
if test "$$dir" != "$$file" && test "$$dir" != "."; then \ |
dir="/$$dir"; \ |
$(mkdir_p) "$(distdir)$$dir"; \ |
else \ |
dir=''; \ |
fi; \ |
if test -d $$d/$$file; then \ |
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ |
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ |
fi; \ |
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ |
else \ |
test -f $(distdir)/$$file \ |
|| cp -p $$d/$$file $(distdir)/$$file \ |
|| exit 1; \ |
fi; \ |
done |
list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ |
if test "$$subdir" = .; then :; else \ |
test -d "$(distdir)/$$subdir" \ |
|| $(mkdir_p) "$(distdir)/$$subdir" \ |
|| exit 1; \ |
distdir=`$(am__cd) $(distdir) && pwd`; \ |
top_distdir=`$(am__cd) $(top_distdir) && pwd`; \ |
(cd $$subdir && \ |
$(MAKE) $(AM_MAKEFLAGS) \ |
top_distdir="$$top_distdir" \ |
distdir="$$distdir/$$subdir" \ |
distdir) \ |
|| exit 1; \ |
fi; \ |
done |
check-am: all-am |
check: check-recursive |
all-am: Makefile $(LIBRARIES) |
installdirs: installdirs-recursive |
installdirs-am: |
install: install-recursive |
install-exec: install-exec-recursive |
install-data: install-data-recursive |
uninstall: uninstall-recursive |
|
install-am: all-am |
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am |
|
installcheck: installcheck-recursive |
install-strip: |
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ |
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ |
`test -z '$(STRIP)' || \ |
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install |
mostlyclean-generic: |
|
clean-generic: |
|
distclean-generic: |
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) |
|
maintainer-clean-generic: |
@echo "This command is intended for maintainers to use" |
@echo "it deletes files that may require special tools to rebuild." |
clean: clean-recursive |
|
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am |
|
distclean: distclean-recursive |
-rm -rf ./$(DEPDIR) |
-rm -f Makefile |
distclean-am: clean-am distclean-compile distclean-generic \ |
distclean-tags |
|
dvi: dvi-recursive |
|
dvi-am: |
|
html: html-recursive |
|
info: info-recursive |
|
info-am: |
|
install-data-am: |
|
install-exec-am: |
|
install-info: install-info-recursive |
|
install-man: |
|
installcheck-am: |
|
maintainer-clean: maintainer-clean-recursive |
-rm -rf ./$(DEPDIR) |
-rm -f Makefile |
maintainer-clean-am: distclean-am maintainer-clean-generic |
|
mostlyclean: mostlyclean-recursive |
|
mostlyclean-am: mostlyclean-compile mostlyclean-generic |
|
pdf: pdf-recursive |
|
pdf-am: |
|
ps: ps-recursive |
|
ps-am: |
|
uninstall-am: uninstall-info-am |
|
uninstall-info: uninstall-info-recursive |
|
.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \ |
clean clean-generic clean-noinstLIBRARIES clean-recursive \ |
ctags ctags-recursive distclean distclean-compile \ |
distclean-generic distclean-recursive distclean-tags distdir \ |
dvi dvi-am html html-am info info-am install install-am \ |
install-data install-data-am install-exec install-exec-am \ |
install-info install-info-am install-man install-strip \ |
installcheck installcheck-am installdirs installdirs-am \ |
maintainer-clean maintainer-clean-generic \ |
maintainer-clean-recursive mostlyclean mostlyclean-compile \ |
mostlyclean-generic mostlyclean-recursive pdf pdf-am ps ps-am \ |
tags tags-recursive uninstall uninstall-am uninstall-info-am |
|
# Tell versions [3.59,3.63) of GNU make to not export all variables. |
# Otherwise a system limit (for SysV at least) may be exceeded. |
.NOEXPORT: |
/channels/Makefile.in
0,0 → 1,435
# Makefile.in generated by automake 1.9.5 from Makefile.am. |
# @configure_input@ |
|
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, |
# 2003, 2004, 2005 Free Software Foundation, Inc. |
# This Makefile.in is free software; the Free Software Foundation |
# gives unlimited permission to copy and/or distribute it, |
# with or without modifications, as long as this notice is preserved. |
|
# This program is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without |
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A |
# PARTICULAR PURPOSE. |
|
@SET_MAKE@ |
|
# Makefile -- Makefile for peripherals channels to host |
# Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
# |
# This file is part of OpenRISC 1000 Architectural Simulator. |
# |
# This program is free software; you can redistribute it and/or modify |
# it under the terms of the GNU General Public License as published by |
# the Free Software Foundation; either version 2 of the License, or |
# (at your option) any later version. |
# |
# This program 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 General Public License for more details. |
# |
# You should have received a copy of the GNU General Public License |
# along with this program; if not, write to the Free Software |
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
# |
|
SOURCES = $(libchannels_a_SOURCES) |
|
srcdir = @srcdir@ |
top_srcdir = @top_srcdir@ |
VPATH = @srcdir@ |
pkgdatadir = $(datadir)/@PACKAGE@ |
pkglibdir = $(libdir)/@PACKAGE@ |
pkgincludedir = $(includedir)/@PACKAGE@ |
top_builddir = ../.. |
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd |
INSTALL = @INSTALL@ |
install_sh_DATA = $(install_sh) -c -m 644 |
install_sh_PROGRAM = $(install_sh) -c |
install_sh_SCRIPT = $(install_sh) -c |
INSTALL_HEADER = $(INSTALL_DATA) |
transform = $(program_transform_name) |
NORMAL_INSTALL = : |
PRE_INSTALL = : |
POST_INSTALL = : |
NORMAL_UNINSTALL = : |
PRE_UNINSTALL = : |
POST_UNINSTALL = : |
build_triplet = @build@ |
host_triplet = @host@ |
target_triplet = @target@ |
subdir = peripheral/channels |
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in |
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 |
am__aclocal_m4_deps = $(top_srcdir)/configure.in |
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ |
$(ACLOCAL_M4) |
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs |
CONFIG_HEADER = $(top_builddir)/config.h |
CONFIG_CLEAN_FILES = |
LIBRARIES = $(noinst_LIBRARIES) |
libchannels_a_AR = $(AR) $(ARFLAGS) |
libchannels_a_LIBADD = |
am_libchannels_a_OBJECTS = channel.$(OBJEXT) fd.$(OBJEXT) \ |
file.$(OBJEXT) generic.$(OBJEXT) xterm.$(OBJEXT) tcp.$(OBJEXT) \ |
tty.$(OBJEXT) |
libchannels_a_OBJECTS = $(am_libchannels_a_OBJECTS) |
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) |
depcomp = $(SHELL) $(top_srcdir)/depcomp |
am__depfiles_maybe = depfiles |
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ |
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) |
CCLD = $(CC) |
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ |
SOURCES = $(libchannels_a_SOURCES) |
DIST_SOURCES = $(libchannels_a_SOURCES) |
ETAGS = etags |
CTAGS = ctags |
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) |
ACLOCAL = @ACLOCAL@ |
AMDEP_FALSE = @AMDEP_FALSE@ |
AMDEP_TRUE = @AMDEP_TRUE@ |
AMTAR = @AMTAR@ |
AR = @AR@ |
ARFLAGS = @ARFLAGS@ |
AUTOCONF = @AUTOCONF@ |
AUTOHEADER = @AUTOHEADER@ |
AUTOMAKE = @AUTOMAKE@ |
AWK = @AWK@ |
BUILD_DIR = @BUILD_DIR@ |
CC = @CC@ |
CCDEPMODE = @CCDEPMODE@ |
CFLAGS = @CFLAGS@ |
CPP = @CPP@ |
CPPFLAGS = @CPPFLAGS@ |
CPU_ARCH = @CPU_ARCH@ |
CYGPATH_W = @CYGPATH_W@ |
DEFS = @DEFS@ |
DEPDIR = @DEPDIR@ |
DYNAMIC_EXECUTION_FALSE = @DYNAMIC_EXECUTION_FALSE@ |
DYNAMIC_EXECUTION_TRUE = @DYNAMIC_EXECUTION_TRUE@ |
ECHO_C = @ECHO_C@ |
ECHO_N = @ECHO_N@ |
ECHO_T = @ECHO_T@ |
EGREP = @EGREP@ |
EXEEXT = @EXEEXT@ |
GENERATE_NEEDED_FALSE = @GENERATE_NEEDED_FALSE@ |
GENERATE_NEEDED_TRUE = @GENERATE_NEEDED_TRUE@ |
INCLUDES = @INCLUDES@ |
INSTALL_DATA = @INSTALL_DATA@ |
INSTALL_PROGRAM = @INSTALL_PROGRAM@ |
INSTALL_SCRIPT = @INSTALL_SCRIPT@ |
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ |
LDFLAGS = @LDFLAGS@ |
LIBOBJS = @LIBOBJS@ |
LIBS = @LIBS@ |
LOCAL_CFLAGS = @LOCAL_CFLAGS@ |
LOCAL_DEFS = @LOCAL_DEFS@ |
LOCAL_LDFLAGS = @LOCAL_LDFLAGS@ |
LTLIBOBJS = @LTLIBOBJS@ |
MAKEINFO = @MAKEINFO@ |
MAKE_SHELL = @MAKE_SHELL@ |
OBJEXT = @OBJEXT@ |
PACKAGE = @PACKAGE@ |
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ |
PACKAGE_NAME = @PACKAGE_NAME@ |
PACKAGE_STRING = @PACKAGE_STRING@ |
PACKAGE_TARNAME = @PACKAGE_TARNAME@ |
PACKAGE_VERSION = @PACKAGE_VERSION@ |
PATH_SEPARATOR = @PATH_SEPARATOR@ |
RANLIB = @RANLIB@ |
SET_MAKE = @SET_MAKE@ |
SHELL = @SHELL@ |
STRIP = @STRIP@ |
SUMVERSION = @SUMVERSION@ |
TERMCAP_LIB = @TERMCAP_LIB@ |
VERSION = @VERSION@ |
ac_ct_CC = @ac_ct_CC@ |
ac_ct_RANLIB = @ac_ct_RANLIB@ |
ac_ct_STRIP = @ac_ct_STRIP@ |
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ |
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ |
am__include = @am__include@ |
am__leading_dot = @am__leading_dot@ |
am__quote = @am__quote@ |
am__tar = @am__tar@ |
am__untar = @am__untar@ |
bindir = @bindir@ |
build = @build@ |
build_alias = @build_alias@ |
build_cpu = @build_cpu@ |
build_os = @build_os@ |
build_vendor = @build_vendor@ |
datadir = @datadir@ |
exec_prefix = @exec_prefix@ |
host = @host@ |
host_alias = @host_alias@ |
host_cpu = @host_cpu@ |
host_os = @host_os@ |
host_vendor = @host_vendor@ |
includedir = @includedir@ |
infodir = @infodir@ |
install_sh = @install_sh@ |
libdir = @libdir@ |
libexecdir = @libexecdir@ |
localstatedir = @localstatedir@ |
mandir = @mandir@ |
mkdir_p = @mkdir_p@ |
oldincludedir = @oldincludedir@ |
prefix = @prefix@ |
program_transform_name = @program_transform_name@ |
sbindir = @sbindir@ |
sharedstatedir = @sharedstatedir@ |
sysconfdir = @sysconfdir@ |
target = @target@ |
target_alias = @target_alias@ |
target_cpu = @target_cpu@ |
target_os = @target_os@ |
target_vendor = @target_vendor@ |
noinst_LIBRARIES = libchannels.a |
libchannels_a_SOURCES = \ |
channel.c \ |
fd.c \ |
file.c \ |
generic.c \ |
xterm.c \ |
tcp.c \ |
tty.c |
|
all: all-am |
|
.SUFFIXES: |
.SUFFIXES: .c .o .obj |
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) |
@for dep in $?; do \ |
case '$(am__configure_deps)' in \ |
*$$dep*) \ |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ |
&& exit 0; \ |
exit 1;; \ |
esac; \ |
done; \ |
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu peripheral/channels/Makefile'; \ |
cd $(top_srcdir) && \ |
$(AUTOMAKE) --gnu peripheral/channels/Makefile |
.PRECIOUS: Makefile |
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status |
@case '$?' in \ |
*config.status*) \ |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ |
*) \ |
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ |
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ |
esac; |
|
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh |
|
$(top_srcdir)/configure: $(am__configure_deps) |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh |
$(ACLOCAL_M4): $(am__aclocal_m4_deps) |
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh |
|
clean-noinstLIBRARIES: |
-test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) |
libchannels.a: $(libchannels_a_OBJECTS) $(libchannels_a_DEPENDENCIES) |
-rm -f libchannels.a |
$(libchannels_a_AR) libchannels.a $(libchannels_a_OBJECTS) $(libchannels_a_LIBADD) |
$(RANLIB) libchannels.a |
|
mostlyclean-compile: |
-rm -f *.$(OBJEXT) |
|
distclean-compile: |
-rm -f *.tab.c |
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/channel.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fd.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/file.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/generic.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tcp.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tty.Po@am__quote@ |
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/xterm.Po@am__quote@ |
|
.c.o: |
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ |
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCC_FALSE@ $(COMPILE) -c $< |
|
.c.obj: |
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \ |
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ |
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ |
@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` |
uninstall-info-am: |
|
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) |
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
unique=`for i in $$list; do \ |
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
done | \ |
$(AWK) ' { files[$$0] = 1; } \ |
END { for (i in files) print i; }'`; \ |
mkid -fID $$unique |
tags: TAGS |
|
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ |
$(TAGS_FILES) $(LISP) |
tags=; \ |
here=`pwd`; \ |
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
unique=`for i in $$list; do \ |
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
done | \ |
$(AWK) ' { files[$$0] = 1; } \ |
END { for (i in files) print i; }'`; \ |
if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ |
test -n "$$unique" || unique=$$empty_fix; \ |
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ |
$$tags $$unique; \ |
fi |
ctags: CTAGS |
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ |
$(TAGS_FILES) $(LISP) |
tags=; \ |
here=`pwd`; \ |
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ |
unique=`for i in $$list; do \ |
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ |
done | \ |
$(AWK) ' { files[$$0] = 1; } \ |
END { for (i in files) print i; }'`; \ |
test -z "$(CTAGS_ARGS)$$tags$$unique" \ |
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ |
$$tags $$unique |
|
GTAGS: |
here=`$(am__cd) $(top_builddir) && pwd` \ |
&& cd $(top_srcdir) \ |
&& gtags -i $(GTAGS_ARGS) $$here |
|
distclean-tags: |
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags |
|
distdir: $(DISTFILES) |
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \ |
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \ |
list='$(DISTFILES)'; for file in $$list; do \ |
case $$file in \ |
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \ |
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \ |
esac; \ |
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ |
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ |
if test "$$dir" != "$$file" && test "$$dir" != "."; then \ |
dir="/$$dir"; \ |
$(mkdir_p) "$(distdir)$$dir"; \ |
else \ |
dir=''; \ |
fi; \ |
if test -d $$d/$$file; then \ |
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ |
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ |
fi; \ |
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ |
else \ |
test -f $(distdir)/$$file \ |
|| cp -p $$d/$$file $(distdir)/$$file \ |
|| exit 1; \ |
fi; \ |
done |
check-am: all-am |
check: check-am |
all-am: Makefile $(LIBRARIES) |
installdirs: |
install: install-am |
install-exec: install-exec-am |
install-data: install-data-am |
uninstall: uninstall-am |
|
install-am: all-am |
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am |
|
installcheck: installcheck-am |
install-strip: |
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ |
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ |
`test -z '$(STRIP)' || \ |
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install |
mostlyclean-generic: |
|
clean-generic: |
|
distclean-generic: |
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) |
|
maintainer-clean-generic: |
@echo "This command is intended for maintainers to use" |
@echo "it deletes files that may require special tools to rebuild." |
clean: clean-am |
|
clean-am: clean-generic clean-noinstLIBRARIES mostlyclean-am |
|
distclean: distclean-am |
-rm -rf ./$(DEPDIR) |
-rm -f Makefile |
distclean-am: clean-am distclean-compile distclean-generic \ |
distclean-tags |
|
dvi: dvi-am |
|
dvi-am: |
|
html: html-am |
|
info: info-am |
|
info-am: |
|
install-data-am: |
|
install-exec-am: |
|
install-info: install-info-am |
|
install-man: |
|
installcheck-am: |
|
maintainer-clean: maintainer-clean-am |
-rm -rf ./$(DEPDIR) |
-rm -f Makefile |
maintainer-clean-am: distclean-am maintainer-clean-generic |
|
mostlyclean: mostlyclean-am |
|
mostlyclean-am: mostlyclean-compile mostlyclean-generic |
|
pdf: pdf-am |
|
pdf-am: |
|
ps: ps-am |
|
ps-am: |
|
uninstall-am: uninstall-info-am |
|
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \ |
clean-noinstLIBRARIES ctags distclean distclean-compile \ |
distclean-generic distclean-tags distdir dvi dvi-am html \ |
html-am info info-am install install-am install-data \ |
install-data-am install-exec install-exec-am install-info \ |
install-info-am install-man install-strip installcheck \ |
installcheck-am installdirs maintainer-clean \ |
maintainer-clean-generic mostlyclean mostlyclean-compile \ |
mostlyclean-generic pdf pdf-am ps ps-am tags uninstall \ |
uninstall-am uninstall-info-am |
|
# Tell versions [3.59,3.63) of GNU make to not export all variables. |
# Otherwise a system limit (for SysV at least) may be exceeded. |
.NOEXPORT: |
/channels/xterm.c
0,0 → 1,267
/* xterm.c -- Definition of functions and structures for |
peripheral to communicate with host through an xterm. |
Inspired from SWI-Prolog by Jan Wielemaker (GPL too) |
even if there is really few in common. |
|
Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
/* |
* I really dislike using stuff beginning with '_' |
* They are suppose to be reserved for the compiler |
* as explained in C standards. |
*/ |
#if HAVE_CONFIG_H |
#include <config.h> |
#endif |
|
#define _XOPEN_SOURCE /* grantpt() and al. */ |
#define _GNU_SOURCE /* on_exit */ |
|
#include <sys/types.h> /* waitpid() */ |
#include <sys/wait.h> /* waitpid() */ |
#include <stdio.h> /* sprintf() */ |
#include <stdlib.h> /* kill(), on_exit() */ |
#include <unistd.h> /* close() */ |
#include <fcntl.h> /* O_RDWR */ |
#include <string.h> /* strchr() */ |
|
#ifndef __CYGWIN__ |
#if HAVE_SYS_STROPTS_H |
#include <sys/stropts.h> /* grantpt(), unlockpt() */ |
#endif |
#include <libgen.h> /* basename() */ |
#endif /* __CYGWIN__ */ |
|
#include <termios.h> /* struct termios and al. */ |
#include <signal.h> /* signal() and al. */ |
#include <errno.h> /* errno and al. */ |
|
#include "channel.h" |
#include "generic.h" |
#include "fd.h" |
|
struct xterm_channel |
{ |
struct fd_channel fds; |
int pid; |
char** argv; |
}; |
|
#ifdef __CYGWIN__ |
char *basename(const char *filename) |
{ |
char *p = strrchr (filename, '/'); |
|
return p ? p + 1 : (char *) filename; |
} |
#endif /* __CYGWIN__ */ |
|
static void xterm_close(void * data) |
{ |
struct xterm_channel * xt = data; |
|
if(!xt) |
return; |
|
if(xt->fds.fdin != -1) |
close(xt->fds.fdin); |
|
if(xt->pid != -1) |
{ |
kill(xt->pid, SIGKILL); |
waitpid(xt->pid, NULL, 0); |
} |
|
if (xt->argv) |
free (xt->argv); |
|
xt->fds.fdin = -1; |
xt->fds.fdout = -1; |
xt->pid = -1; |
xt->argv = NULL; |
|
} |
|
#if defined(HAS_ON_EXIT) |
static void xterm_exit(int i, void * data) |
{ |
xterm_close(data); |
} |
#endif |
|
#define MAX_XTERM_ARGS 100 |
static void * xterm_init(const char * input) |
{ |
struct xterm_channel * retval = malloc(sizeof(struct xterm_channel)); |
if(retval) |
{ |
int i; |
char *arglist; |
|
retval->fds.fdin = -1; |
retval->fds.fdout = -1; |
retval->pid = -1; |
|
#if defined(HAS_ON_EXIT) |
/* reset cause exit(1), leaving an xterm opened */ |
on_exit(xterm_exit, retval); |
#endif |
|
i = 2; |
arglist = (char*)input; |
retval->argv = malloc(sizeof(char*) * MAX_XTERM_ARGS); |
if (!retval->argv) { |
free(retval); |
return NULL; |
} |
/* Assume xterm arguments are separated by whitespace */ |
while ((retval->argv[i++] = strtok(arglist, " \t\n"))) { |
arglist = NULL; |
if (i == MAX_XTERM_ARGS - 1) { |
free(retval); |
return NULL; |
} |
} |
|
} |
return (void*)retval; |
} |
|
|
|
static int xterm_open(void * data) |
{ |
#if defined(HAS_GRANTPT) && defined(HAS_UNLOCKPT) && defined(HAS_PTSNAME) |
struct xterm_channel * xt = data; |
int master, retval; |
char * slavename; |
struct termios termio; |
char arg[64], * fin; |
|
if(!data) |
{ |
errno = ENODEV; |
return -1; |
} |
|
master = open("/dev/ptmx", O_RDWR); |
|
if(master < 0) |
return -1; |
|
grantpt(master); |
unlockpt(master); |
slavename = (char*)ptsname(master); |
|
if(!slavename) |
{ |
errno = ENOTTY; |
goto closemastererror; |
} |
|
xt->fds.fdout = xt->fds.fdin = open(slavename, O_RDWR); |
if(xt->fds.fdout < 0) goto closemastererror; |
|
//#if !defined(linux) && !defined(__CYGWIN__) |
#if defined(I_PUSH) |
/* Linux does not support STREAMS-style line discipline, even with LiS. */ |
retval = ioctl(xt->fds.fdin, I_PUSH, "ptem"); |
if(retval < 0) goto closeslaveerror; |
|
retval = ioctl(xt->fds.fdin, I_PUSH, "ldterm"); |
if(retval < 0) goto closeslaveerror; |
#endif |
|
retval = tcgetattr(xt->fds.fdin, &termio); |
if(retval < 0) goto closeslaveerror; |
termio.c_lflag &= ~ECHO; |
retval = tcsetattr(xt->fds.fdin, TCSADRAIN, &termio); |
if(retval < 0) goto closeslaveerror; |
|
xt->pid = fork(); |
|
if(xt->pid == -1) goto closeslaveerror; |
|
if(xt->pid == 0) |
{ |
/* Ctrl-C on sim still kill the xterm, grrr */ |
signal(SIGINT, SIG_IGN); |
|
fin = slavename+strlen(slavename)-2; |
if (strchr(fin, '/' )) |
{ |
sprintf(arg, "-S%s/%d", |
basename(slavename), |
master); |
} |
else |
{ |
sprintf(arg, "-S%c%c%d", fin[0], fin[1], master); |
} |
xt->argv[0] = "xterm"; |
xt->argv[1] = arg; |
execvp("xterm", xt->argv); |
write(master, "\n", 1); |
exit(1); |
} |
|
do retval = read(xt->fds.fdin, &arg, 1); |
while(retval >= 0 && arg[0] != '\n'); |
if(retval < 0) goto closeslaveerror; |
|
termio.c_lflag |= ECHO; |
retval = tcsetattr(xt->fds.fdin, TCSADRAIN, &termio); |
|
if(retval < 0) goto closeslaveerror; |
|
return 0; |
|
closeslaveerror: |
close(xt->fds.fdin); |
|
closemastererror: |
close(master); |
xt->pid = xt->fds.fdin = xt->fds.fdout = -1; |
return -1; |
|
#else |
/* I don't see how this stuff should be working on a system that doesn't know |
grantpt(), unlockpt(), ptsname(). Mac OS X also does not have /dev/ptmx. |
-hpanther |
*/ |
return -1; |
#endif |
} |
|
struct channel_ops xterm_channel_ops = |
{ |
init: xterm_init, |
open: xterm_open, |
close: xterm_close, |
read: fd_read, |
write: fd_write, |
free: generic_free, |
}; |
|
/* |
* Local variables: |
* c-file-style: "linux" |
* End: |
*/ |
|
/channels/tty.c
0,0 → 1,186
/* tty.c -- Definition of functions for peripheral to |
* communicate with host via a tty. |
|
Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#include <stdio.h> |
#include <termios.h> |
#include <unistd.h> |
#include <string.h> |
#include <fcntl.h> |
#include <stdlib.h> |
|
#include "channel.h" |
#include "generic.h" |
#include "fd.h" |
|
// Default parameters if not specified in config file |
#define DEFAULT_BAUD B19200 |
#define DEFAULT_TTY_DEVICE "/dev/ttyS0" |
|
struct tty_channel |
{ |
struct fd_channel fds; |
}; |
|
static struct { |
char* name; |
int value; |
} baud_table[] = { |
{"50", B50}, |
{"2400", B2400}, |
{"4800", B4800}, |
{"9600", B9600}, |
{"19200", B19200}, |
{"38400", B38400}, |
{"115200", B115200}, |
{"230400", B230400}, |
{0, 0} |
}; |
|
// Convert baud rate string to termio baud rate constant |
int |
parse_baud(char* baud_string) |
{ |
int i; |
for (i = 0; baud_table[i].name; i++) { |
if (!strcmp(baud_table[i].name, baud_string)) |
return baud_table[i].value; |
} |
|
fprintf(stderr, "Error: unknown baud rate: %s\n", baud_string); |
fprintf(stderr, " Known baud rates: "); |
|
for (i = 0; baud_table[i].name; i++) { |
fprintf(stderr, "%s%s", baud_table[i].name, baud_table[i+1].name ? ", " : "\n"); |
} |
return B0; |
} |
|
static void * tty_init(const char * input) |
{ |
int fd = 0, baud; |
char *param_name, *param_value, *device; |
struct termios options; |
struct tty_channel* channel; |
|
channel = (struct tty_channel*)malloc(sizeof(struct tty_channel)); |
if (!channel) |
return NULL; |
|
// Make a copy of config string, because we're about to mutate it |
input = strdup(input); |
if (!input) |
goto error; |
|
baud = DEFAULT_BAUD; |
device = DEFAULT_TTY_DEVICE; |
|
// Parse command-line parameters |
// Command line looks like name1=value1,name2,name3=value3,... |
while ((param_name = strtok((char*)input, ","))) { |
|
input = NULL; |
|
// Parse a parameter's name and value |
param_value = strchr(param_name,'='); |
if (param_value != NULL) { |
*param_value = '\0'; |
param_value++; // Advance past '=' character |
} |
|
if (!strcmp(param_name, "baud") && param_value) { |
baud = parse_baud(param_value); |
if (baud == B0) { |
goto error; |
} |
} else if (!strcmp(param_name, "device")) { |
device = param_value; |
} else { |
fprintf(stderr, "error: unknown tty channel parameter \"%s\"\n", param_name); |
goto error; |
} |
} |
|
fd = open(device, O_RDWR); |
if (fd < 0) |
goto error; |
|
// Get the current options for the port... |
if (tcgetattr(fd, &options) < 0) |
goto error; |
|
// Set the serial baud rate |
cfsetispeed(&options, baud); |
cfsetospeed(&options, baud); |
|
// Enable the receiver and set local mode... |
|
/* cfmakeraw(&options); |
* |
* cygwin lacks cfmakeraw(), just do it explicitly |
*/ |
options.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP |
|INLCR|IGNCR|ICRNL|IXON); |
options.c_oflag &= ~OPOST; |
options.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN); |
options.c_cflag &= ~(CSIZE|PARENB); |
options.c_cflag |= CS8; |
|
options.c_cflag |= (CLOCAL | CREAD); |
|
|
// Set the new options for the port... |
if (tcsetattr(fd, TCSANOW, &options) < 0) |
goto error; |
|
channel->fds.fdin = channel->fds.fdout = fd; |
free((void *)input); |
return channel; |
|
error: |
if (fd > 0) |
close(fd); |
free(channel); |
if (input) |
free((void *)input); |
return NULL; |
} |
|
static int tty_open(void * data) |
{ |
return 0; |
} |
|
struct channel_ops tty_channel_ops = |
{ |
init: tty_init, |
open: tty_open, |
close: generic_close, |
read: fd_read, |
write: fd_write, |
free: generic_free, |
}; |
|
/* |
* Local variables: |
* c-file-style: "linux" |
* End: |
*/ |
|
/channels/tcp.c
0,0 → 1,182
/* tcp.c -- Definition of functions for peripheral to |
* communicate with host via a tcp socket. |
|
Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
|
#include <stdio.h> |
#include <sys/types.h> |
#include <sys/socket.h> |
#include <netinet/in.h> |
#include <fcntl.h> |
#include <errno.h> |
#include <stdlib.h> |
#include <string.h> |
#include <unistd.h> |
|
#include "channel.h" |
#include "generic.h" |
#include "fd.h" |
|
struct tcp_channel |
{ |
struct fd_channel fds; |
int socket_fd; /* Socket to listen to */ |
int port_number; /* TCP port number */ |
int connected; /* If 0, no remote endpoint yet */ |
int nonblocking; /* If 0, read/write will block until |
remote client connects */ |
}; |
|
static void * tcp_init(const char * input) |
{ |
int port_number, fd, flags; |
struct sockaddr_in local_ip; |
struct tcp_channel* channel = (struct tcp_channel*)malloc(sizeof(struct tcp_channel)); |
if (!channel) |
return NULL; |
|
fd = 0; |
channel->nonblocking = 1; |
channel->fds.fdin = -1; |
channel->fds.fdout = -1; |
channel->socket_fd = -1; |
channel->port_number = -1; |
|
port_number = atoi(input); |
if (port_number == 0) |
goto error; |
|
fd = socket(AF_INET, SOCK_STREAM, 0); |
if (fd < 0) |
goto error; |
|
flags = 1; |
if(setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&flags,sizeof(int)) < 0) |
{ |
perror("Can not set SO_REUSEADDR option on channel socket"); |
goto error; |
} |
|
memset(&local_ip, 0, sizeof(local_ip)); |
local_ip.sin_family = AF_INET; |
local_ip.sin_addr.s_addr = htonl(INADDR_ANY); |
local_ip.sin_port = htons(port_number); |
if (bind(fd, (struct sockaddr*)&local_ip, sizeof(local_ip)) < 0) { |
perror("Can't bind local address"); |
goto error; |
} |
|
if (channel->nonblocking) { |
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) |
{ |
perror("Can not make channel socket non-blocking"); |
goto error; |
} |
} |
|
if (listen(fd, 1) < 0) |
goto error; |
|
channel->socket_fd = fd; |
channel->port_number = port_number; |
channel->connected = 0; |
return (void*)channel; |
|
error: |
if (fd) |
close(fd); |
free(channel); |
return NULL; |
} |
|
static int tcp_open(void * data) |
{ |
/* Socket is opened lazily, upon first read or write, so do nothing here */ |
return 0; |
} |
|
|
static int wait_for_tcp_connect(struct tcp_channel* channel) |
{ |
int fd; |
socklen_t sizeof_remote_ip; |
struct sockaddr_in remote_ip; |
|
sizeof_remote_ip = sizeof(remote_ip); |
fd = accept(channel->socket_fd, (struct sockaddr*)&remote_ip, &sizeof_remote_ip); |
if (fd < 0) { |
if (channel->nonblocking) { |
/* Not an error if there is not yet a remote connection - try again later */ |
if (errno == EAGAIN) |
return 0; |
} |
perror("Couldn't accept connection"); |
return -1; |
} |
|
channel->fds.fdin = channel->fds.fdout = fd; |
close(channel->socket_fd); |
channel->socket_fd = -1; |
channel->connected = 1; |
return 1; |
} |
|
static int tcp_read(void * data, char * buffer, int size) |
{ |
struct tcp_channel* channel = data; |
|
/* Lazily connect to tcp partner on read/write */ |
if (!channel->connected) { |
int retval = wait_for_tcp_connect(data); |
if (retval <= 0) |
return retval; |
} |
return fd_read(data, buffer, size); |
} |
|
static int tcp_write(void * data, const char * buffer, int size) |
{ |
struct tcp_channel* channel = data; |
|
/* Lazily connect to tcp partner on read/write */ |
if (!channel->connected) { |
int retval = wait_for_tcp_connect(data); |
if (retval < 0) |
return retval; |
} |
return fd_write(data, buffer, size); |
} |
|
struct channel_ops tcp_channel_ops = |
{ |
init: tcp_init, |
open: tcp_open, |
close: generic_close, |
read: tcp_read, |
write: tcp_write, |
free: generic_free, |
}; |
|
/* |
* Local variables: |
* c-file-style: "linux" |
* End: |
*/ |
|
/channels/channel.c
0,0 → 1,256
/* channel.c -- Definition of types and structures for |
peripherals to communicate with host. Adapted from UML. |
|
Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#if HAVE_CONFIG_H |
#include "config.h" |
#endif |
|
#define _GNU_SOURCE /* for strndup */ |
|
#include <stdio.h> /* perror */ |
#include <stdlib.h> /* exit */ |
|
#if HAVE_MALLOC_H |
#include <malloc.h> /* calloc, free */ |
#endif |
|
#include <string.h> /* strndup, strcmp, strlen, strchr */ |
#include <errno.h> /* errno */ |
|
#include "port.h" |
|
#include "channel.h" |
|
struct channel_factory |
{ |
const char * name; |
const struct channel_ops * ops; |
struct channel_factory * next; |
}; |
|
extern struct channel_ops fd_channel_ops, file_channel_ops, |
xterm_channel_ops, tcp_channel_ops, tty_channel_ops; |
|
static struct channel_factory preloaded[] = |
{ |
{ "fd", &fd_channel_ops, &preloaded[1] }, |
{ "file", &file_channel_ops, &preloaded[2] }, |
{ "xterm", &xterm_channel_ops, &preloaded[3] }, |
{ "tcp", &tcp_channel_ops, &preloaded[4] }, |
{ "tty", &tty_channel_ops, NULL } |
}; |
|
static struct channel_factory * head = &preloaded[0]; |
|
static struct channel_factory * find_channel_factory(const char * name); |
|
struct channel * channel_init(const char * descriptor) |
{ |
struct channel * retval; |
struct channel_factory * current; |
char * args, * name; |
int count; |
|
if(!descriptor) |
{ |
return NULL; |
} |
|
retval = (struct channel*)calloc(1, sizeof(struct channel)); |
|
if(!retval) |
{ |
perror(descriptor); |
exit(1); |
} |
|
args = strchr(descriptor, ':'); |
|
if(args) |
{ |
count = args - descriptor; |
args++; |
} |
else |
{ |
count = strlen(descriptor); |
} |
|
name = (char*)strndup(descriptor, count); |
|
if(!name) |
{ |
perror(name); |
exit(1); |
} |
|
current = find_channel_factory(name); |
|
if(!current) |
{ |
errno = ENODEV; |
perror(descriptor); |
exit(1); |
} |
|
retval->ops = current->ops; |
|
free(name); |
|
if(!retval->ops) |
{ |
errno = ENODEV; |
perror(descriptor); |
exit(1); |
} |
|
if(retval->ops->init) |
{ |
retval->data = (retval->ops->init)(args); |
|
if(!retval->data) |
{ |
perror(descriptor); |
exit(1); |
} |
} |
|
return retval; |
} |
|
int channel_open(struct channel * channel) |
{ |
if(channel && channel->ops && channel->ops->open) |
{ |
return (channel->ops->open)(channel->data); |
} |
errno = ENOSYS; |
return -1; |
} |
|
int channel_read(struct channel * channel, char * buffer, int size) |
{ |
if(channel && channel->ops && channel->ops->read) |
{ |
return (channel->ops->read)(channel->data, buffer, size); |
} |
errno = ENOSYS; |
return -1; |
} |
|
int channel_write(struct channel * channel, const char * buffer, int size) |
{ |
if(channel && channel->ops && channel->ops->write) |
{ |
return (channel->ops->write)(channel->data, buffer, size); |
} |
errno = ENOSYS; |
return -1; |
} |
|
void channel_close(struct channel * channel) |
{ |
if(channel && channel->ops && channel->ops->close) |
{ |
(channel->ops->close)(channel->data); |
} |
} |
|
void channel_free(struct channel * channel) |
{ |
if(channel && channel->ops && channel->ops->free) |
{ |
(channel->ops->free)(channel->data); |
free(channel); |
} |
} |
|
|
int channel_ok(struct channel * channel) |
{ |
if(channel && channel->ops) |
{ |
if(channel->ops->isok) |
return (channel->ops->isok)(channel->data); |
else |
return 1; |
} |
return 0; |
} |
|
char * channel_status(struct channel * channel) |
{ |
if(channel && channel->ops && channel->ops->status) |
{ |
return (channel->ops->status)(channel->data); |
} |
return ""; |
} |
|
|
|
static struct channel_factory * find_channel_factory(const char * name) |
{ |
struct channel_factory * current = head; |
|
current = head; |
while(current && strcmp(current->name, name)) |
{ |
current = current->next; |
} |
|
return current; |
} |
|
int register_channel(const char * name, const struct channel_ops * ops) |
{ |
struct channel_factory * new; |
|
|
if(find_channel_factory(name)) |
{ |
errno = EEXIST; |
perror(name); |
exit(1); |
} |
|
new = (struct channel_factory *)calloc(1, sizeof(struct channel_factory)); |
|
if(!new) |
{ |
perror(name); |
exit(1); |
} |
|
new->name = name; |
new->ops = ops; |
new->next = head; |
head = new; |
|
return (int)new; /* dummy */ |
} |
|
/* |
* Local variables: |
* c-file-style: "linux" |
* End: |
*/ |
|
/channels/file.c
0,0 → 1,162
/* file.c -- Definition of functions and structures for |
peripheral to communicate with host through files |
|
Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#if HAVE_CONFIG_H |
#include <config.h> |
#endif |
|
#define _GNU_SOURCE /* for strndup */ |
|
#include <sys/types.h> /* open() */ |
#include <sys/stat.h> /* open() */ |
#include <fcntl.h> /* open() */ |
#if HAVE_MALLOC_H |
#include <malloc.h> /* calloc, free */ |
#endif |
#include <string.h> /* strndup(), strchr() */ |
#include <errno.h> /* errno */ |
#include <unistd.h> /* close() */ |
|
#include "channel.h" /* struct channel_ops */ |
#include "fd.h" /* struct fd_channel, fd_read(), fd_write() */ |
|
struct file_channel |
{ |
struct fd_channel fds; |
char * namein; |
char * nameout; |
}; |
|
static void * file_init(const char * args) |
{ |
struct file_channel * retval; |
char * nameout; |
|
if(!args) |
{ |
errno = EINVAL; |
return NULL; |
} |
|
retval = (struct file_channel*)calloc(1, sizeof(struct file_channel)); |
|
if(!retval) |
{ |
return NULL; |
} |
|
retval->fds.fdin = -1; |
retval->fds.fdout = -1; |
|
nameout = strchr(args, ','); |
|
if(nameout) |
{ |
retval->namein = strndup(args, nameout - args); |
retval->nameout = strdup(nameout+1); |
} |
else |
{ |
retval->nameout = retval->namein = strdup(args); |
} |
|
return (void*)retval; |
} |
|
static int file_open(void * data) |
{ |
struct file_channel * files = (struct file_channel *)data; |
|
if(!files) |
{ |
errno = ENODEV; |
return -1; |
} |
|
if(files->namein == files->nameout) |
{ |
/* if we have the same name in and out |
* it cannot (logically) be a regular files. |
* so we wont create one |
*/ |
files->fds.fdin = files->fds.fdout = open(files->namein, O_RDWR); |
|
return files->fds.fdin < 0 ? -1 : 0; |
} |
|
|
files->fds.fdin = open(files->namein, O_RDONLY | O_CREAT, 0664); |
|
if(files->fds.fdin < 0) |
return -1; |
|
files->fds.fdout = open(files->nameout, O_WRONLY | O_CREAT, 0664); |
|
if(files->fds.fdout < 0) |
{ |
close(files->fds.fdout); |
files->fds.fdout = -1; |
return -1; |
} |
|
return 0; |
} |
|
static void file_close(void * data) |
{ |
struct file_channel * files = (struct file_channel *)data; |
|
if(files->fds.fdin != files->fds.fdout) |
close(files->fds.fdin); |
|
close(files->fds.fdout); |
|
files->fds.fdin = -1; |
files->fds.fdout = -1; |
} |
|
static void file_free(void * data) |
{ |
struct file_channel * files = (struct file_channel *)data; |
|
if(files->namein != files->nameout) |
free(files->namein); |
|
free(files->nameout); |
|
free(files); |
} |
|
struct channel_ops file_channel_ops = |
{ |
init: file_init, |
open: file_open, |
close: file_close, |
read: fd_read, |
write: fd_write, |
free: file_free, |
}; |
|
/* |
* Local variables: |
* c-file-style: "linux" |
* End: |
*/ |
/channels/fd.c
0,0 → 1,160
/* fd.c -- Definition of functions and structures for |
peripheral to communicate with host through file descriptors |
|
Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#if HAVE_CONFIG_H |
#include <config.h> |
#endif |
|
#include <sys/time.h> /* struct timeval */ |
#include <sys/types.h> /* fd_set */ |
#include <stdio.h> /* perror */ |
#include <stdlib.h> /* atoi */ |
#include <unistd.h> /* read, write, select */ |
#if HAVE_MALLOC_H |
#include <malloc.h> /* calloc, free */ |
#endif |
#include <string.h> /* strchr */ |
#include <errno.h> /* errno */ |
|
#include "channel.h" |
#include "generic.h" |
#include "fd.h" |
|
static void * fd_init(const char * args) |
{ |
struct fd_channel * retval; |
|
retval = (struct fd_channel*)calloc(1, sizeof(struct fd_channel)); |
|
if(!retval) |
{ |
return NULL; |
} |
|
|
retval->fdin = atoi(args); /* so 0 if garbage */ |
/* TODO: strtoul */ |
|
args = strchr(args, ','); |
|
if(args) |
{ |
retval->fdout = atoi(args+1); |
} |
else |
{ |
retval->fdout = retval->fdin; |
} |
|
return (void*)retval; |
} |
|
int fd_read(void * data, char * buffer, int size) |
{ |
struct fd_channel * fds = (struct fd_channel *)data; |
struct timeval timeout = { 0, 0 }; |
fd_set rfds; |
int retval; |
|
if(!fds) |
{ |
errno = ENODEV; |
return -1; |
} |
|
FD_ZERO(&rfds); |
FD_SET(fds->fdin, &rfds); |
|
retval = select(fds->fdin+1, &rfds, NULL, NULL, &timeout); |
|
if(retval <= 0) |
return retval; |
|
return read(fds->fdin, buffer, size); |
} |
|
int fd_write(void * data, const char * buffer, int size) |
{ |
struct fd_channel * fds = (struct fd_channel *)data; |
if(fds) |
{ |
return write(fds->fdout, buffer, size); |
} |
errno = ENODEV; |
return -1; |
} |
|
static int fd_isok(void * data) |
{ |
struct fd_channel * fds = (struct fd_channel *)data; |
if(fds) |
{ |
return fds->fdout != -1 && fds->fdin != -1; |
} |
return 0; |
} |
|
static int fd_status_fd(int fd, char * str, int size) |
{ |
if(fd == -1) |
return snprintf(str, size, "closed"); |
|
return snprintf(str, size, "opened(fd=%d)", fd); |
} |
|
char * fd_status(void * data) |
{ |
static char retval[256]; |
int index = 0; |
|
struct fd_channel * fds = (struct fd_channel *)data; |
if(fds) |
{ |
index += snprintf(retval + index, sizeof(retval) - index, "in "); |
index += fd_status_fd(fds->fdin, retval + index, sizeof(retval) - index); |
|
index += snprintf(retval + index, sizeof(retval) - index, "out "); |
index += fd_status_fd(fds->fdout, retval + index, sizeof(retval) - index); |
} |
else |
{ |
snprintf(retval, sizeof(retval), "(null)"); |
} |
return retval; |
} |
|
struct channel_ops fd_channel_ops = |
{ |
init: fd_init, |
open: generic_open, |
close: generic_close, |
read: fd_read, |
write: fd_write, |
free: generic_free, |
isok: fd_isok, |
status: fd_status, |
}; |
|
/* |
* Local variables: |
* c-file-style: "linux" |
* End: |
*/ |
/channels/generic.c
0,0 → 1,61
/* generic.c -- Definition of generic functions for peripheral to |
* communicate with host |
|
Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#if HAVE_CONFIG_H |
#include <config.h> |
#endif |
|
#if HAVE_MALLOC_H |
#include <malloc.h> /* calloc, free */ |
#endif |
|
#include <errno.h> /* errno */ |
|
|
int generic_open(void * data) |
{ |
if(data) |
{ |
return 0; |
} |
errno = ENODEV; |
return -1; |
} |
|
void generic_close(void * data) |
{ |
return; |
} |
|
void generic_free(void * data) |
{ |
if(data) |
{ |
free(data); |
} |
} |
|
|
/* |
* Local variables: |
* c-file-style: "linux" |
* End: |
*/ |
/channels/Makefile.am
0,0 → 1,30
# Makefile -- Makefile for peripherals channels to host |
# Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
# |
# This file is part of OpenRISC 1000 Architectural Simulator. |
# |
# This program is free software; you can redistribute it and/or modify |
# it under the terms of the GNU General Public License as published by |
# the Free Software Foundation; either version 2 of the License, or |
# (at your option) any later version. |
# |
# This program 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 General Public License for more details. |
# |
# You should have received a copy of the GNU General Public License |
# along with this program; if not, write to the Free Software |
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
# |
|
noinst_LIBRARIES = libchannels.a |
libchannels_a_SOURCES = \ |
channel.c \ |
fd.c \ |
file.c \ |
generic.c \ |
xterm.c \ |
tcp.c \ |
tty.c |
|
/channels/fd.h
0,0 → 1,34
/* generic.h -- Declaration of generic functions for peripheral to |
* communicate with host |
|
Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#ifndef FD_H |
#define FD_H |
|
struct fd_channel |
{ |
int fdin; |
int fdout; |
}; |
|
int fd_read(void * data, char * buffer, int size); |
int fd_write(void * data, const char * buffer, int size); |
|
#endif |
/channels/generic.h
0,0 → 1,29
/* generic.h -- Declaration of generic functions for peripheral to |
* communicate with host |
|
Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#ifndef GENERIC_H |
#define GENERIC_H |
|
int generic_open(void * data); |
void generic_close(void * data); |
void generic_free(void * data); |
|
#endif |
/channels/channel.h
0,0 → 1,68
/* channel.h -- Definition of types and structures for |
peripheral to communicate with host. Addapted from UML. |
|
Copyright (C) 2002 Richard Prescott <rip@step.polymtl.ca> |
|
This file is part of OpenRISC 1000 Architectural Simulator. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program 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 General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ |
|
#ifndef CHANNEL_H |
#define CHANNEL_H |
|
struct channel_ops |
{ |
void *(*init)(const char *); |
int (*open)(void *); |
void (*close)(void *); |
int (*read)(void *, char *, int); |
int (*write)(void *, const char *, int); |
void (*free)(void *); |
int (*isok)(void*); |
char* (*status)(void*); |
}; |
|
struct channel |
{ |
const struct channel_ops * ops; |
void * data; |
}; |
|
|
struct channel * channel_init(const char * descriptor); |
/* read operation in non-blocking */ |
int channel_open(struct channel * channel); |
int channel_read(struct channel * channel, char * buffer, int size); |
int channel_write(struct channel * channel, const char * buffer, int size); |
void channel_free(struct channel * channel); |
int channel_ok(struct channel * channel); |
char * channel_status(struct channel * channel); |
|
void channel_close(struct channel * channel); |
|
int register_channel(const char * name, const struct channel_ops * ops); |
/* TODO: int unregister_channel(const char * name); */ |
|
/* for those who wants to automatically register at startup */ |
#define REGISTER_CHANNEL(NAME,OPS) \ |
static int NAME ## _dummy_register = register_channel(#NAME, OPS) |
|
#endif |
|
/* |
* Local variables: |
* c-file-style: "linux" |
* End: |
*/ |
channels
Property changes :
Added: svn:ignore
## -0,0 +1,2 ##
+Makefile
+.deps
Index: ps2kbd.c
===================================================================
--- ps2kbd.c (nonexistent)
+++ ps2kbd.c (revision 1765)
@@ -0,0 +1,376 @@
+/* ps2kbd.c -- Very simple (and limited) PS/2 keyboard simulation
+ Copyright (C) 2002 Marko Mlinar, markom@opencores.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include
+#include
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "ps2kbd.h"
+#include "sim-config.h"
+#include "abstract.h"
+#include "sched.h"
+#include "pic.h"
+
+/* ASCII to scan code conversion table */
+const static struct {
+ /* Whether shift must be pressed */
+ unsigned char shift;
+ /* Scan code to be generated */
+ unsigned char code;
+} scan_table [128] = {
+/* 0 - 15 */
+{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
+{0, 0x0E}, {0, 0x0F}, {0, 0x1C}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
+/* 16 - 31 */
+{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
+{0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x01}, {0, 0x00}, {0, 0x00}, {0, 0x00}, {0, 0x00},
+/* 32 - 47 */
+{0, 0x39}, {1, 0x02}, {1, 0x28}, {1, 0x04}, {1, 0x05}, {1, 0x06}, {1, 0x08}, {0, 0x28},
+{1, 0x0A}, {1, 0x0B}, {1, 0x09}, {1, 0x0D}, {0, 0x33}, {0, 0x0C}, {0, 0x34}, {0, 0x35},
+/* 48 - 63 */
+{0, 0x0B}, {0, 0x02}, {0, 0x03}, {0, 0x04}, {0, 0x05}, {0, 0x06}, {0, 0x07}, {0, 0x08},
+{0, 0x09}, {0, 0x0A}, {1, 0x27}, {0, 0x27}, {1, 0x33}, {0, 0x0D}, {1, 0x34}, {1, 0x35},
+/* 64 - 79 */
+{1, 0x03}, {1, 0x1E}, {1, 0x30}, {1, 0x2E}, {1, 0x20}, {1, 0x12}, {1, 0x21}, {1, 0x22},
+{1, 0x23}, {1, 0x17}, {1, 0x24}, {1, 0x25}, {1, 0x26}, {1, 0x32}, {1, 0x31}, {1, 0x18},
+/* 80 - 95 */
+{1, 0x19}, {1, 0x10}, {1, 0x13}, {1, 0x1F}, {1, 0x14}, {1, 0x16}, {1, 0x2F}, {1, 0x11},
+{1, 0x2D}, {1, 0x15}, {1, 0x2C}, {0, 0x1A}, {0, 0x2B}, {0, 0x1B}, {1, 0x07}, {1, 0x0C},
+/* 96 - 111 */
+{0, 0x29}, {0, 0x1E}, {0, 0x30}, {0, 0x2E}, {0, 0x20}, {0, 0x12}, {0, 0x21}, {0, 0x22},
+{0, 0x23}, {0, 0x17}, {0, 0x24}, {0, 0x25}, {0, 0x26}, {0, 0x32}, {0, 0x31}, {0, 0x18},
+/* 112 - 127 */
+{0, 0x19}, {0, 0x10}, {0, 0x13}, {0, 0x1F}, {0, 0x14}, {0, 0x16}, {0, 0x2F}, {0, 0x11},
+{0, 0x2D}, {0, 0x15}, {0, 0x2C}, {1, 0x1A}, {1, 0x2B}, {1, 0x1B}, {1, 0x29}, {0, 0x00}
+};
+
+struct kbd_state {
+ /* Temporary buffer to store incoming scan codes */
+ uint8_t buf[KBD_MAX_BUF];
+
+ /* Number of scan codes in buffer */
+ unsigned long buf_count;
+ unsigned long buf_head;
+ unsigned long buf_tail;
+
+ /* Input stream */
+ FILE *rxfs;
+
+ /* Controller Command (write into 0x64) */
+ int ccmd;
+
+ /* Keyboard Command (write into 0x60) */
+ uint8_t kcmd;
+
+ /* Controller Command Byte */
+ uint8_t ccmdbyte;
+
+ /* Keyboard response pending */
+ unsigned long kresp;
+
+ /* Keyboard slowdown factor */
+ long slowdown;
+
+ /* Cofiguration */
+ int enabled;
+ int irq;
+ oraddr_t baseaddr;
+ char *rxfile;
+};
+
+static void kbd_put (struct kbd_state *kbd, unsigned char c)
+{
+ if (kbd->buf_count >= KBD_MAX_BUF) {
+ fprintf (stderr, "WARNING: Keyboard buffer overflow.\n");
+ } else {
+ kbd->buf[kbd->buf_head] = c;
+ kbd->buf_head = (kbd->buf_head + 1) % KBD_MAX_BUF;
+ kbd->buf_count++;
+ }
+}
+
+/* Decodes ascii code c into multiple scan codes, placed into buf, length is returned */
+static void scan_decode (struct kbd_state *kbd, unsigned char c)
+{
+ /* Do not handle special characters and extended ascii */
+ if (c >= 128 || !scan_table[c].code)
+ return;
+
+ /* Make shift? */
+ if (scan_table[c].shift) kbd_put (kbd, 0x2a);
+ /* Make char */
+ kbd_put (kbd, scan_table[c].code);
+ /* Break char */
+ kbd_put (kbd, scan_table[c].code | 0x80);
+ /* Break shift? */
+ if (scan_table[c].shift) kbd_put (kbd, 0xaa);
+}
+
+/* Write a register */
+void kbd_write8 (oraddr_t addr, uint8_t value, void *dat)
+{
+ struct kbd_state *kbd = dat;
+ switch (addr) {
+ case KBD_CTRL:
+ kbd->ccmd = value & 0xff;
+ if (kbd->ccmd == KBD_CCMD_RCB)
+ kbd->kresp = 0x1;
+ if (kbd->ccmd == KBD_CCMD_ST1)
+ kbd->kresp = 0x1;
+ if (kbd->ccmd == KBD_CCMD_ST2)
+ kbd->kresp = 0x1;
+ if (kbd->ccmd == KBD_CCMD_DKI)
+ kbd->ccmdbyte |= KBD_CCMDBYTE_EN;
+ if (kbd->ccmd == KBD_CCMD_EKI)
+ kbd->ccmdbyte &= ~KBD_CCMDBYTE_EN;
+ if (config.sim.verbose)
+ PRINTF("kbd_write8(%"PRIxADDR") %"PRIx32"\n", addr, value);
+ break;
+ case KBD_DATA:
+ if (kbd->ccmd == KBD_CCMD_WCB) {
+ kbd->ccmdbyte = value & 0xff;
+ kbd->ccmd = 0x00;
+ } else
+ kbd->kcmd = value & 0xff;
+ if (kbd->kcmd == KBD_KCMD_DK)
+ kbd->ccmdbyte |= KBD_CCMDBYTE_EN;
+ if (kbd->kcmd == KBD_KCMD_EK)
+ kbd->ccmdbyte &= ~KBD_CCMDBYTE_EN;
+ kbd->kresp = 0x1;
+ kbd->ccmd = 0x00;
+ if (config.sim.verbose)
+ PRINTF("kbd_write8(%"PRIxADDR") %"PRIx32"\n", addr, value);
+ break;
+ default:
+ fprintf (stderr, "Write out of keyboard space (0x%"PRIxADDR")!\n", addr);
+ break;
+ }
+}
+
+/* Read a register */
+uint8_t kbd_read8 (oraddr_t addr, void *dat)
+{
+ struct kbd_state *kbd = dat;
+ switch (addr) {
+ case KBD_CTRL: {
+ unsigned long c = 0x0;
+ if (kbd->kresp || kbd->buf_count)
+ c |= KBD_STATUS_OBF;
+ c |= kbd->ccmdbyte & KBD_CCMDBYTE_SYS;
+ c |= KBD_STATUS_INH;
+ if (config.sim.verbose)
+ PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, c);
+ return c;
+ }
+ case KBD_DATA:
+ if (kbd->ccmd) {
+ unsigned long rc = 0;
+ if (kbd->ccmd == KBD_CCMD_RCB)
+ rc = kbd->ccmdbyte;
+ if (kbd->ccmd == KBD_CCMD_ST1)
+ rc = 0x55;
+ if (kbd->ccmd == KBD_CCMD_ST2)
+ rc = 0x00;
+ kbd->ccmd = 0x00;
+ kbd->kresp = 0x0;
+ if (config.sim.verbose)
+ PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, rc);
+ return rc;
+ }
+ else if (kbd->kresp) {
+ unsigned long rc;
+ if (kbd->kresp == 0x2) {
+ kbd->kresp = 0x0;
+ rc = KBD_KRESP_RSTOK;
+ } else if (kbd->kcmd == KBD_KCMD_RST) {
+ kbd->kresp = 0x2;
+ rc = KBD_KRESP_ACK;
+ } else if (kbd->kcmd == KBD_KCMD_ECHO) {
+ kbd->kresp = 0x0;
+ rc = KBD_KRESP_ECHO;
+ } else {
+ kbd->kresp = 0x0;
+ rc = KBD_KRESP_ACK;
+ }
+ kbd->kcmd = 0x00;
+ if (config.sim.verbose)
+ PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, rc);
+ return rc;
+ } else if (kbd->buf_count) {
+ unsigned long c = kbd->buf[kbd->buf_tail];
+ kbd->buf_tail = (kbd->buf_tail + 1) % KBD_MAX_BUF;
+ kbd->buf_count--;
+ kbd->kresp = 0x0;
+ if (config.sim.verbose)
+ PRINTF("kbd_read8(%"PRIxADDR") %lx\n", addr, c);
+ return c;
+ }
+ kbd->kresp = 0x0;
+ if (config.sim.verbose)
+ PRINTF("kbd_read8(%"PRIxADDR") fifo empty\n", addr);
+ return 0;
+ default:
+ fprintf (stderr, "Read out of keyboard space (0x%"PRIxADDR")!\n", addr);
+ return 0;
+ }
+}
+
+
+/* Simulation hook. Must be called every couple of clock cycles to simulate incomming data. */
+void kbd_job(void *dat)
+{
+ struct kbd_state *kbd = dat;
+ int c;
+ int kbd_int = 0;
+
+ /* Check if there is something waiting, and decode it into kdb_buf */
+ if((c = fgetc(kbd->rxfs)) != EOF) {
+ scan_decode (kbd, c);
+ }
+ kbd_int = kbd->kresp || kbd->buf_count ? kbd->ccmdbyte & KBD_CCMDBYTE_INT : 0;
+/*
+ if (config.sim.verbose && kbd_int)
+ PRINTF("Keyboard Interrupt.... kbd_kresp %lx kbd_buf_count %lx \n",
+ kbd->kresp, kbd->buf_count);
+*/
+ if (kbd_int) report_interrupt(kbd->irq);
+ SCHED_ADD(kbd_job, dat, kbd->slowdown);
+}
+
+/* Reset all (simulated) ps2 controlers/keyboards */
+void kbd_reset (void *dat)
+{
+ struct kbd_state *kbd = dat;
+
+ kbd->buf_count = 0;
+ kbd->buf_head = 0;
+ kbd->buf_tail = 0;
+ kbd->kresp = 0x0;
+ kbd->ccmdbyte = 0x65; /* We reset into default normal operation. */
+
+ if (!(kbd->rxfs = fopen(kbd->rxfile, "r"))
+ && !(kbd->rxfs = fopen(kbd->rxfile, "r+"))) {
+ fprintf (stderr, "WARNING: Unable to open RX file stream.\n");
+ return;
+ }
+ kbd->slowdown = (long) ((config.sim.system_kfreq * 1000.) / KBD_BAUD_RATE);
+ if (kbd->slowdown <= 0) kbd->slowdown = 1;
+ SCHED_ADD(kbd_job, dat, kbd->slowdown);
+}
+
+
+void kbd_info(void *dat)
+{
+ struct kbd_state *kbd = dat;
+ PRINTF("kbd_kcmd: %x\n", kbd->kcmd);
+ PRINTF("kbd_ccmd: %x\n", kbd->ccmd);
+ PRINTF("kbd_ccmdbyte: %x\n", kbd->ccmdbyte);
+ PRINTF("kbd_kresp: %lx\n", kbd->kresp);
+ PRINTF("kbd_buf_count: %lx\n", kbd->buf_count);
+}
+
+/*----------------------------------------------------[ KBD Configuration ]---*/
+void kbd_baseaddr(union param_val val, void *dat)
+{
+ struct kbd_state *kbd = dat;
+ kbd->baseaddr = val.addr_val;
+}
+
+void kbd_irq(union param_val val, void *dat)
+{
+ struct kbd_state *kbd = dat;
+ kbd->irq = val.int_val;
+}
+
+void kbd_rxfile(union param_val val, void *dat)
+{
+ struct kbd_state *kbd = dat;
+ if(!(kbd->rxfile = strdup(val.str_val))) {
+ fprintf(stderr, "Peripheral KBD: Run out of memory\n");
+ exit(-1);
+ }
+}
+
+void kbd_enabled(union param_val val, void *dat)
+{
+ struct kbd_state *kbd = dat;
+ kbd->enabled = val.int_val;
+}
+
+void *kbd_sec_start(void)
+{
+ struct kbd_state *new = malloc(sizeof(struct kbd_state));
+
+ if(!new) {
+ fprintf(stderr, "Peripheral KBD: Run out of memory\n");
+ exit(-1);
+ }
+
+ new->buf_count = 0;
+ new->buf_head = 0;
+ new->buf_tail = 0;
+ new->rxfs = NULL;
+ new->enabled = 1;
+
+ return new;
+}
+
+void kbd_sec_end(void *dat)
+{
+ struct kbd_state *kbd = dat;
+ struct mem_ops ops;
+
+ if(!kbd->enabled) {
+ free(dat);
+ return;
+ }
+
+ memset(&ops, 0, sizeof(struct mem_ops));
+
+ ops.readfunc8 = kbd_read8;
+ ops.writefunc8 = kbd_write8;
+ ops.read_dat8 = dat;
+ ops.write_dat8 = dat;
+
+ /* FIXME: Correct delay? */
+ ops.delayr = 2;
+ ops.delayw = 2;
+
+ reg_mem_area(kbd->baseaddr, KBD_SPACE, 0, &ops);
+ reg_sim_reset(kbd_reset, dat);
+ reg_sim_stat(kbd_info, dat);
+}
+
+void reg_kbd_sec(void)
+{
+ struct config_section *sec = reg_config_sec("kbd", kbd_sec_start, kbd_sec_end);
+
+ reg_config_param(sec, "baseaddr", paramt_addr, kbd_baseaddr);
+ reg_config_param(sec, "enabled", paramt_int, kbd_enabled);
+ reg_config_param(sec, "irq", paramt_int, kbd_irq);
+ reg_config_param(sec, "rxfile", paramt_str, kbd_rxfile);
+}
ps2kbd.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: gpio.c
===================================================================
--- gpio.c (nonexistent)
+++ gpio.c (revision 1765)
@@ -0,0 +1,320 @@
+/* gpio.h -- GPIO code simulation
+ Copyright (C) 2001 Erez Volk, erez@mailandnews.comopencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "abstract.h"
+#include "gpio.h"
+#include "gpio_i.h"
+#include "sim-config.h"
+#include "pic.h"
+#include "vapi.h"
+#include "debug.h"
+#include "sched.h"
+
+DEFAULT_DEBUG_CHANNEL(gpio);
+
+static void gpio_vapi_read( unsigned long id, unsigned long data, void *dat );
+static uint32_t gpio_read32( oraddr_t addr, void *dat );
+static void gpio_write32( oraddr_t addr, uint32_t value, void *dat );
+
+static void gpio_external_clock( unsigned long value, struct gpio_device *gpio );
+static void gpio_device_clock( struct gpio_device *gpio );
+static void gpio_clock( void *dat );
+
+/* Initialize all parameters and state */
+void gpio_reset( void *dat )
+{
+ struct gpio_device *gpio = dat;
+
+ if ( gpio->baseaddr != 0 ) {
+ /* Possibly connect to VAPI */
+ if ( gpio->base_vapi_id ) {
+ vapi_install_multi_handler( gpio->base_vapi_id, GPIO_NUM_VAPI_IDS, gpio_vapi_read, dat );
+ }
+ }
+ SCHED_ADD(gpio_clock, dat, 1);
+}
+
+
+/* Dump status */
+void gpio_status( void *dat )
+{
+ struct gpio_device *gpio = dat;
+
+ if ( gpio->baseaddr == 0 )
+ return;
+
+ PRINTF( "\nGPIO at 0x%"PRIxADDR":\n", gpio->baseaddr );
+ PRINTF( "RGPIO_IN : 0x%08lX\n", gpio->curr.in );
+ PRINTF( "RGPIO_OUT : 0x%08lX\n", gpio->curr.out );
+ PRINTF( "RGPIO_OE : 0x%08lX\n", gpio->curr.oe );
+ PRINTF( "RGPIO_INTE : 0x%08lX\n", gpio->curr.inte );
+ PRINTF( "RGPIO_PTRIG : 0x%08lX\n", gpio->curr.ptrig );
+ PRINTF( "RGPIO_AUX : 0x%08lX\n", gpio->curr.aux );
+ PRINTF( "RGPIO_CTRL : 0x%08lX\n", gpio->curr.ctrl );
+ PRINTF( "RGPIO_INTS : 0x%08lX\n", gpio->curr.ints );
+}
+
+
+/* Wishbone read */
+uint32_t gpio_read32( oraddr_t addr, void *dat )
+{
+ struct gpio_device *gpio = dat;
+
+ switch( addr ) {
+ case RGPIO_IN: return gpio->curr.in | gpio->curr.out;
+ case RGPIO_OUT: return gpio->curr.out;
+ case RGPIO_OE: return gpio->curr.oe;
+ case RGPIO_INTE: return gpio->curr.inte;
+ case RGPIO_PTRIG: return gpio->curr.ptrig;
+ case RGPIO_AUX: return gpio->curr.aux;
+ case RGPIO_CTRL: return gpio->curr.ctrl;
+ case RGPIO_INTS: return gpio->curr.ints;
+ }
+
+ return 0;
+}
+
+
+/* Wishbone write */
+void gpio_write32( oraddr_t addr, uint32_t value, void *dat )
+{
+ struct gpio_device *gpio = dat;
+
+ switch( addr ) {
+ case RGPIO_IN: TRACE( "GPIO: Cannot write to RGPIO_IN\n" ); break;
+ case RGPIO_OUT: gpio->next.out = value; break;
+ case RGPIO_OE: gpio->next.oe = value; break;
+ case RGPIO_INTE: gpio->next.inte = value; break;
+ case RGPIO_PTRIG: gpio->next.ptrig = value; break;
+ case RGPIO_AUX: gpio->next.aux = value; break;
+ case RGPIO_CTRL: gpio->next.ctrl = value; break;
+ case RGPIO_INTS: gpio->next.ints = value; break;
+ }
+}
+
+
+/* Input from "outside world" */
+void gpio_vapi_read( unsigned long id, unsigned long data, void *dat )
+{
+ unsigned which;
+ struct gpio_device *gpio = dat;
+
+ TRACE( "GPIO: id %08lx, data %08lx\n", id, data );
+
+ which = id - gpio->base_vapi_id;
+
+ switch( which ) {
+ case GPIO_VAPI_DATA:
+ TRACE( "GPIO: Next input from VAPI = 0x%08lx (RGPIO_OE = 0x%08lx)\n",
+ data, gpio->next.oe );
+ gpio->next.in = data;
+ break;
+ case GPIO_VAPI_AUX:
+ gpio->auxiliary_inputs = data;
+ break;
+ case GPIO_VAPI_RGPIO_OE:
+ gpio->next.oe = data;
+ break;
+ case GPIO_VAPI_RGPIO_INTE:
+ gpio->next.inte = data;
+ break;
+ case GPIO_VAPI_RGPIO_PTRIG:
+ gpio->next.ptrig = data;
+ break;
+ case GPIO_VAPI_RGPIO_AUX:
+ gpio->next.aux = data;
+ break;
+ case GPIO_VAPI_RGPIO_CTRL:
+ gpio->next.ctrl = data;
+ break;
+ case GPIO_VAPI_CLOCK:
+ gpio_external_clock( data, gpio );
+ break;
+ }
+}
+
+/* System Clock. */
+static void gpio_clock( void *dat )
+{
+ struct gpio_device *gpio = dat;
+
+ /* Clock the device */
+ if ( !(gpio->curr.ctrl & RGPIO_CTRL_ECLK) )
+ gpio_device_clock( gpio );
+ SCHED_ADD(gpio_clock, dat, 1);
+}
+
+/* External Clock. */
+static void gpio_external_clock( unsigned long value, struct gpio_device *gpio )
+{
+ int use_external_clock = ((gpio->curr.ctrl & RGPIO_CTRL_ECLK) == RGPIO_CTRL_ECLK);
+ int negative_edge = ((gpio->curr.ctrl & RGPIO_CTRL_NEC) == RGPIO_CTRL_NEC);
+
+ /* "Normalize" clock value */
+ value = (value != 0);
+
+ gpio->next.external_clock = value;
+
+ if ( use_external_clock && (gpio->next.external_clock != gpio->curr.external_clock) && (value != negative_edge) )
+ /* Make sure that in vapi_read, we don't clock the device */
+ if ( gpio->curr.ctrl & RGPIO_CTRL_ECLK )
+ gpio_device_clock( gpio );
+}
+
+/* Report an interrupt to the sim */
+void gpio_do_int( void *dat )
+{
+ struct gpio_device *gpio = dat;
+
+ report_interrupt( gpio->irq );
+}
+
+/* Clock as handld by one device. */
+static void gpio_device_clock( struct gpio_device *gpio )
+{
+ /* Calculate new inputs and outputs */
+ gpio->next.in &= ~gpio->next.oe; /* Only input bits */
+ /* Replace requested output bits with aux input */
+ gpio->next.out = (gpio->next.out & ~gpio->next.aux) | (gpio->auxiliary_inputs & gpio->next.aux);
+ gpio->next.out &= gpio->next.oe; /* Only output-enabled bits */
+
+ /* If any outputs changed, notify the world (i.e. vapi) */
+ if ( gpio->next.out != gpio->curr.out ) {
+ TRACE( "GPIO: New output 0x%08lx, RGPIO_OE = 0x%08lx\n", gpio->next.out,
+ gpio->next.oe );
+ if ( gpio->base_vapi_id )
+ vapi_send( gpio->base_vapi_id + GPIO_VAPI_DATA, gpio->next.out );
+ }
+
+ /* If any inputs changed and interrupt enabled, generate interrupt */
+ if ( gpio->next.in != gpio->curr.in ) {
+ TRACE( "GPIO: New input 0x%08lx\n", gpio->next.in );
+
+ if ( gpio->next.ctrl & RGPIO_CTRL_INTE ) {
+ unsigned changed_bits = gpio->next.in ^ gpio->curr.in; /* inputs that have changed */
+ unsigned set_bits = changed_bits & gpio->next.in; /* inputs that have been set */
+ unsigned cleared_bits = changed_bits & gpio->curr.in; /* inputs that have been cleared */
+ unsigned relevant_bits = (gpio->next.ptrig & set_bits) | (~gpio->next.ptrig & cleared_bits);
+
+ if ( relevant_bits & gpio->next.inte ) {
+ TRACE( "GPIO: Reporting interrupt %d\n", gpio->irq );
+ gpio->next.ctrl |= RGPIO_CTRL_INTS;
+ gpio->next.ints |= relevant_bits & gpio->next.inte;
+ /* Since we can't report an interrupt during a readmem/writemem
+ * schedule the scheduler to do it. Read the comment above
+ * report_interrupt in pic/pic.c */
+ SCHED_ADD( gpio_do_int, gpio, 1 );
+ }
+ }
+ }
+
+ /* Switch to values for next clock */
+ memcpy( &(gpio->curr), &(gpio->next), sizeof(gpio->curr) );
+}
+
+/*---------------------------------------------------[ GPIO configuration ]---*/
+void gpio_baseaddr(union param_val val, void *dat)
+{
+ struct gpio_device *gpio = dat;
+ gpio->baseaddr = val.addr_val;
+}
+
+void gpio_irq(union param_val val, void *dat)
+{
+ struct gpio_device *gpio = dat;
+ gpio->irq = val.int_val;
+}
+
+void gpio_base_vapi_id(union param_val val, void *dat)
+{
+ struct gpio_device *gpio = dat;
+ gpio->base_vapi_id = val.int_val;
+}
+
+void gpio_enabled(union param_val val, void *dat)
+{
+ struct gpio_device *gpio = dat;
+ gpio->enabled = val.int_val;
+}
+
+void *gpio_sec_start(void)
+{
+ struct gpio_device *new = malloc(sizeof(struct gpio_device));
+
+ if(!new) {
+ fprintf(stderr, "Peripheral gpio: Run out of memory\n");
+ exit(-1);
+ }
+
+ new->auxiliary_inputs = 0;
+ memset(&new->curr, 0, sizeof(new->curr));
+ memset(&new->next, 0, sizeof(new->next));
+
+ new->enabled = 1;
+
+ return new;
+}
+
+void gpio_sec_end(void *dat)
+{
+ struct gpio_device *gpio = dat;
+ struct mem_ops ops;
+
+ if(!gpio->enabled) {
+ free(dat);
+ return;
+ }
+
+ memset(&ops, 0, sizeof(struct mem_ops));
+
+ ops.readfunc32 = gpio_read32;
+ ops.writefunc32 = gpio_write32;
+ ops.write_dat32 = dat;
+ ops.read_dat32 = dat;
+
+ /* FIXME: Correct delays? */
+ ops.delayr = 2;
+ ops.delayw = 2;
+
+ /* Register memory range */
+ reg_mem_area( gpio->baseaddr, GPIO_ADDR_SPACE, 0, &ops );
+
+ reg_sim_reset(gpio_reset, dat);
+ reg_sim_stat(gpio_status, dat);
+}
+
+void reg_gpio_sec(void)
+{
+ struct config_section *sec = reg_config_sec("gpio", gpio_sec_start, gpio_sec_end);
+
+ reg_config_param(sec, "enabled", paramt_int, gpio_enabled);
+ reg_config_param(sec, "baseaddr", paramt_addr, gpio_baseaddr);
+ reg_config_param(sec, "irq", paramt_int, gpio_irq);
+ reg_config_param(sec, "base_vapi_id", paramt_int, gpio_base_vapi_id);
+}
Index: 16450.c
===================================================================
--- 16450.c (nonexistent)
+++ 16450.c (revision 1765)
@@ -0,0 +1,1102 @@
+/* 16450.c -- Simulation of 8250/16450 serial UART
+ Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* This is functional simulation of 8250/16450 UARTs. Since we RX/TX data
+ via file streams, we can't simulate modem control lines coming from the
+ DCE and similar details of communication with the DCE.
+
+ This simulated UART device is intended for basic UART device driver
+ verification. From device driver perspective this device looks like a
+ regular UART but never reports any modem control lines changes (the
+ only DCE responses are incoming characters from the file stream).
+*/
+
+#include
+#include
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "abstract.h"
+#include "16450.h"
+#include "sim-config.h"
+#include "pic.h"
+#include "vapi.h"
+#include "sched.h"
+#include "channel.h"
+#include "debug.h"
+
+DEFAULT_DEBUG_CHANNEL(uart);
+
+#define MIN(a,b) ((a) < (b) ? (a) : (b))
+
+void uart_recv_break(void *dat);
+void uart_recv_char(void *dat);
+void uart_check_vapi(void *dat);
+void uart_check_char(void *dat);
+static void uart_sched_recv_check(struct dev_16450 *uart);
+static void uart_vapi_cmd(void *dat);
+static void uart_clear_int(struct dev_16450 *uart, int intr);
+void uart_tx_send(void *dat);
+
+/* Number of clock cycles (one clock cycle is when UART_CLOCK_DIVIDER simulator
+ * cycles have elapsed) before a single character is transmitted or received. */
+static unsigned long char_clks(int dll, int dlh, int lcr)
+{
+ unsigned int bauds_per_char = 2;
+ unsigned long char_clks = ((dlh << 8) + dll);
+
+ if (lcr & UART_LCR_PARITY)
+ bauds_per_char += 2;
+
+ /* stop bits 1 or two */
+ if (lcr & UART_LCR_STOP)
+ bauds_per_char += 4;
+ else
+ if ((lcr & 0x3) != 0)
+ bauds_per_char += 2;
+ else
+ bauds_per_char += 3;
+
+ bauds_per_char += 10 + ((lcr & 0x3) << 1);
+
+ return (char_clks * bauds_per_char) >> 1;
+}
+
+/*---------------------------------------------------[ Interrupt handling ]---*/
+/* Signals the specified interrupt. If a higher priority interrupt is already
+ * pending, do nothing */
+static void uart_int_msi(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ uart->istat.ints |= 1 << UART_IIR_MSI;
+
+ if(!(uart->regs.ier & UART_IER_MSI))
+ return;
+
+ if((uart->regs.iir & UART_IIR_NO_INT) || (uart->regs.iir == UART_IIR_MSI)) {
+ TRACE("Raiseing modem status interrupt\n");
+
+ if((uart->regs.iir != UART_IIR_MSI) && (uart->regs.iir != UART_IIR_NO_INT)) {
+ uart_clear_int(uart, uart->regs.iir);
+ uart->regs.iir = UART_IIR_MSI;
+ } else {
+ uart->regs.iir = UART_IIR_MSI;
+ SCHED_ADD(uart_int_msi, dat, UART_CLOCK_DIVIDER);
+ report_interrupt(uart->irq);
+ }
+ }
+}
+
+static void uart_int_thri(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ uart->istat.ints |= 1 << UART_IIR_THRI;
+
+ if(!(uart->regs.ier & UART_IER_THRI))
+ return;
+
+ if((uart->regs.iir & UART_IIR_NO_INT) || (uart->regs.iir == UART_IIR_MSI) ||
+ (uart->regs.iir == UART_IIR_THRI)) {
+ TRACE("Raiseing transmitter holding register interrupt\n");
+
+ if((uart->regs.iir != UART_IIR_THRI) && (uart->regs.iir != UART_IIR_NO_INT)) {
+ uart_clear_int(uart, uart->regs.iir);
+ uart->regs.iir = UART_IIR_THRI;
+ } else {
+ uart->regs.iir = UART_IIR_THRI;
+ SCHED_ADD(uart_int_thri, dat, UART_CLOCK_DIVIDER);
+ report_interrupt(uart->irq);
+ }
+ }
+}
+
+static void uart_int_cti(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ uart->istat.ints |= 1 << UART_IIR_CTI;
+
+ if(!(uart->regs.ier & UART_IER_RDI))
+ return;
+
+ if((uart->regs.iir != UART_IIR_RLSI) && (uart->regs.iir != UART_IIR_RDI)) {
+ TRACE("Raiseing character timeout interrupt\n");
+
+ if((uart->regs.iir != UART_IIR_CTI) && (uart->regs.iir != UART_IIR_NO_INT)) {
+ uart_clear_int(uart, uart->regs.iir);
+ uart->regs.iir = UART_IIR_CTI;
+ } else {
+ uart->regs.iir = UART_IIR_CTI;
+ SCHED_ADD(uart_int_cti, dat, UART_CLOCK_DIVIDER);
+ report_interrupt(uart->irq);
+ }
+ }
+}
+
+static void uart_int_rdi(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ uart->istat.ints |= 1 << UART_IIR_RDI;
+
+ if(!(uart->regs.ier & UART_IER_RDI))
+ return;
+
+ if(uart->regs.iir != UART_IIR_RLSI) {
+ TRACE("Raiseing receiver data interrupt\n");
+
+ if((uart->regs.iir != UART_IIR_RDI) && (uart->regs.iir != UART_IIR_NO_INT)) {
+ uart_clear_int(uart, uart->regs.iir);
+ uart->regs.iir = UART_IIR_RDI;
+ } else {
+ uart->regs.iir = UART_IIR_RDI;
+ SCHED_ADD(uart_int_rdi, dat, UART_CLOCK_DIVIDER);
+ report_interrupt(uart->irq);
+ }
+ }
+}
+
+static void uart_int_rlsi(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ uart->istat.ints |= 1 << UART_IIR_RLSI;
+
+ if(!(uart->regs.ier & UART_IER_RLSI))
+ return;
+
+ TRACE("Raiseing receiver line status interrupt\n");
+
+ /* Highest priority interrupt */
+ if((uart->regs.iir != UART_IIR_RLSI) && (uart->regs.iir != UART_IIR_NO_INT)) {
+ uart_clear_int(uart, uart->regs.iir);
+ uart->regs.iir = UART_IIR_RLSI;
+ } else {
+ uart->regs.iir = UART_IIR_RLSI;
+ SCHED_ADD(uart_int_rlsi, dat, UART_CLOCK_DIVIDER);
+ report_interrupt(uart->irq);
+ }
+}
+
+/* Checks to see if an RLSI interrupt is due and schedules one if need be */
+static void uart_check_rlsi(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ if(uart->regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY | UART_LSR_FRAME |
+ UART_LSR_BREAK))
+ uart_int_rlsi(uart);
+}
+
+/* Checks to see if an RDI interrupt is due and schedules one if need be */
+static void uart_check_rdi(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ if(uart->istat.rxbuf_full >= UART_FIFO_TRIGGER(uart->regs.fcr >> 6)) {
+ TRACE("FIFO trigger level reached %i\n",
+ UART_FIFO_TRIGGER(uart->regs.fcr >> 6));
+ uart_int_rdi(uart);
+ }
+}
+
+/* Raises the next highest priority interrupt */
+static void uart_next_int(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ /* Interrupt detection in proper priority order. */
+ if((uart->istat.ints & (1 << UART_IIR_RLSI)) &&
+ (uart->regs.ier & UART_IER_RLSI))
+ uart_int_rlsi(uart);
+ else if((uart->istat.ints & (1 << UART_IIR_RDI)) &&
+ (uart->regs.ier & UART_IER_RDI))
+ uart_int_rdi(uart);
+ else if((uart->istat.ints & (1 << UART_IIR_CTI)) &&
+ (uart->regs.ier & UART_IER_RDI))
+ uart_int_cti(uart);
+ else if((uart->istat.ints & (1 << UART_IIR_THRI)) &&
+ (uart->regs.ier & UART_IER_THRI))
+ uart_int_thri(uart);
+ else if((uart->istat.ints & (1 << UART_IIR_MSI)) &&
+ (uart->regs.ier & UART_IER_MSI))
+ uart_int_msi(uart);
+ else
+ uart->regs.iir = UART_IIR_NO_INT;
+}
+
+/* Clears potentially pending interrupts */
+static void uart_clear_int(struct dev_16450 *uart, int intr)
+{
+ uart->istat.ints &= ~(1 << intr);
+
+ TRACE("Interrupt pending was %x\n", uart->regs.iir);
+
+ /* Short-circuit most likely case */
+ if(uart->regs.iir == UART_IIR_NO_INT)
+ return;
+
+ if(intr != uart->regs.iir)
+ return;
+
+ TRACE("Clearing interrupt 0x%x\n", intr);
+
+ uart->regs.iir = UART_IIR_NO_INT;
+
+ switch(intr) {
+ case UART_IIR_RLSI:
+ SCHED_FIND_REMOVE(uart_int_rlsi, uart);
+ break;
+ case UART_IIR_RDI:
+ SCHED_FIND_REMOVE(uart_int_rdi, uart);
+ break;
+ case UART_IIR_CTI:
+ SCHED_FIND_REMOVE(uart_int_cti, uart);
+ break;
+ case UART_IIR_THRI:
+ SCHED_FIND_REMOVE(uart_int_thri, uart);
+ break;
+ case UART_IIR_MSI:
+ SCHED_FIND_REMOVE(uart_int_msi, uart);
+ break;
+ }
+
+ /* Schedule this job as there is no rush to send the next interrupt (the or.
+ * code is probably still running with interrupts disabled and this function
+ * is called from the uart_{read,write}_byte functions. */
+ SCHED_ADD(uart_next_int, uart, 0);
+}
+
+/*----------------------------------------------------[ Loopback handling ]---*/
+static void uart_loopback(struct dev_16450 *uart)
+{
+ if(!(uart->regs.mcr & UART_MCR_LOOP))
+ return;
+
+ if((uart->regs.mcr & UART_MCR_AUX2) != ((uart->regs.msr & UART_MSR_DCD) >> 4))
+ uart->regs.msr |= UART_MSR_DDCD;
+
+ if((uart->regs.mcr & UART_MCR_AUX1) < ((uart->regs.msr & UART_MSR_RI) >> 4))
+ uart->regs.msr |= UART_MSR_TERI;
+
+ if((uart->regs.mcr & UART_MCR_RTS) != ((uart->regs.msr & UART_MSR_CTS) >> 3))
+ uart->regs.msr |= UART_MSR_DCTS;
+
+ if((uart->regs.mcr & UART_MCR_DTR) != ((uart->regs.msr & UART_MSR_DSR) >> 5))
+ uart->regs.msr |= UART_MSR_DDSR;
+
+ uart->regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI | UART_MSR_DSR | UART_MSR_CTS);
+ uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX2) << 4);
+ uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX1) << 4);
+ uart->regs.msr |= ((uart->regs.mcr & UART_MCR_RTS) << 3);
+ uart->regs.msr |= ((uart->regs.mcr & UART_MCR_DTR) << 5);
+
+ if(uart->regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR | UART_MSR_TERI |
+ UART_MSR_DDCD))
+ uart_int_msi(uart);
+}
+
+/*----------------------------------------------------[ Transmitter logic ]---*/
+/* Sends the data in the shift register to the outside world */
+static void send_char (struct dev_16450 *uart, int bits_send)
+{
+ PRINTF ("%c", (char)uart->iregs.txser);
+ TRACE("TX \'%c\' via UART at %"PRIxADDR"\n", (char)uart->iregs.txser,
+ uart->baseaddr);
+ if (uart->regs.mcr & UART_MCR_LOOP)
+ uart->iregs.loopback = uart->iregs.txser;
+ else {
+ /* Send to either VAPI or to file */
+ if (uart->vapi_id) {
+ int par, pe, fe, nbits;
+ int j, data;
+ unsigned long packet = 0;
+
+ nbits = MIN (bits_send, (uart->regs.lcr & UART_LCR_WLEN8) + 5);
+ /* Encode a packet */
+ packet = uart->iregs.txser & ((1 << nbits) - 1);
+
+ /* Calculate parity */
+ for (j = 0, par = 0; j < nbits; j++)
+ par ^= (packet >> j) & 1;
+
+ if (uart->regs.lcr & UART_LCR_PARITY) {
+ if (uart->regs.lcr & UART_LCR_SPAR) {
+ packet |= 1 << nbits;
+ } else {
+ if (uart->regs.lcr & UART_LCR_EPAR)
+ packet |= par << nbits;
+ else
+ packet |= (par ^ 1) << nbits;
+ }
+ nbits++;
+ }
+ packet |= 1 << (nbits++);
+ if (uart->regs.lcr & UART_LCR_STOP)
+ packet |= 1 << (nbits++);
+
+ /* Decode a packet */
+ nbits = (uart->vapi.lcr & UART_LCR_WLEN8) + 5;
+ data = packet & ((1 << nbits) - 1);
+
+ /* Calculate parity, including parity bit */
+ for (j = 0, par = 0; j < nbits + 1; j++)
+ par ^= (packet >> j) & 1;
+
+ if (uart->vapi.lcr & UART_LCR_PARITY) {
+ if (uart->vapi.lcr & UART_LCR_SPAR) {
+ pe = !((packet >> nbits) & 1);
+ } else {
+ if (uart->vapi.lcr & UART_LCR_EPAR)
+ pe = par != 0;
+ else
+ pe = par != 1;
+ }
+ nbits++;
+ } else
+ pe = 0;
+
+ fe = ((packet >> (nbits++)) & 1) ^ 1;
+ if (uart->vapi.lcr & UART_LCR_STOP)
+ fe |= ((packet >> (nbits++)) & 1) ^ 1;
+
+ TRACE ("lcr vapi %02x, uart %02x\n", uart->vapi.lcr, uart->regs.lcr);
+ data |= (uart->vapi.lcr << 8) | (pe << 16) | (fe << 17) | (uart->vapi.lcr << 8);
+ TRACE ("vapi_send (%08lx, %08x)\n", uart->vapi_id, data);
+ vapi_send (uart->vapi_id, data);
+ } else {
+ char buffer[1] = { uart->iregs.txser & 0xFF };
+ channel_write(uart->channel, buffer, 1);
+ }
+ }
+}
+
+/* Called when all the bits have been shifted out of the shift register */
+void uart_char_clock(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ TRACE("Sending data in shift reg: 0x%02"PRIx8"\n", uart->iregs.txser);
+ /* We've sent all bits */
+ send_char(uart, (uart->regs.lcr & UART_LCR_WLEN8) + 5);
+
+ if(!uart->istat.txbuf_full)
+ uart->regs.lsr |= UART_LSR_TXSERE;
+ else
+ uart_tx_send(uart);
+}
+
+/* Called when a break has been shifted out of the shift register */
+void uart_send_break(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ TRACE("Sending break\n");
+#if 0
+ /* Send broken frame */
+ int nbits_sent = ((uart->regs.lcr & UART_LCR_WLEN8) + 5) * (uart->istat.txser_clks - 1) / uart->char_clks;
+ send_char(i, nbits_sent);
+#endif
+ /* Send one break signal */
+ vapi_send (uart->vapi_id, UART_LCR_SBC << 8);
+
+ /* Send the next char (if there is one) */
+ if(!uart->istat.txbuf_full)
+ uart->regs.lsr |= UART_LSR_TXSERE;
+ else
+ uart_tx_send(uart);
+}
+
+/* Scheduled whenever the TX buffer has characters in it and we aren't sending
+ * a character. */
+void uart_tx_send(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ uart->iregs.txser = uart->regs.txbuf[uart->istat.txbuf_tail];
+ uart->istat.txbuf_tail = (uart->istat.txbuf_tail + 1) % uart->fifo_len;
+ uart->istat.txbuf_full--;
+ uart->regs.lsr &= ~UART_LSR_TXSERE;
+
+ TRACE("Moveing head of TX fifo (fill: %i) to shift reg 0x%02"PRIx8"\n",
+ uart->istat.txbuf_full, uart->iregs.txser);
+
+ /* Schedules a char_clock to run in the correct amount of time */
+ if(!(uart->regs.lcr & UART_LCR_SBC)) {
+ SCHED_ADD(uart_char_clock, uart, uart->char_clks * UART_CLOCK_DIVIDER);
+ } else {
+ TRACE("Sending break not char\n");
+ SCHED_ADD(uart_send_break, uart, 0);
+ }
+
+ /* When UART is in either character mode, i.e. 16450 emulation mode, or FIFO
+ * mode, the THRE interrupt is raised when THR transitions from full to empty.
+ */
+ if (!uart->istat.txbuf_full) {
+ uart->regs.lsr |= UART_LSR_TXBUFE;
+ uart_int_thri(uart);
+ }
+}
+
+/*-------------------------------------------------------[ Receiver logic ]---*/
+/* Adds a character to the RX FIFO */
+static void uart_add_char (struct dev_16450 *uart, int ch)
+{
+ uart->regs.lsr |= UART_LSR_RDRDY;
+ uart_clear_int(uart, UART_IIR_CTI);
+ SCHED_FIND_REMOVE(uart_int_cti, uart);
+ SCHED_ADD(uart_int_cti, uart,
+ uart->char_clks * UART_CHAR_TIMEOUT * UART_CLOCK_DIVIDER);
+
+ if (uart->istat.rxbuf_full + 1 > uart->fifo_len) {
+ uart->regs.lsr |= UART_LSR_OVRRUN | UART_LSR_RXERR;
+ uart_int_rlsi(uart);
+ } else {
+ TRACE("add %02x\n", ch);
+ uart->regs.rxbuf[uart->istat.rxbuf_head] = ch;
+ uart->istat.rxbuf_head = (uart->istat.rxbuf_head + 1) % uart->fifo_len;
+ if(!uart->istat.rxbuf_full++) {
+ uart->regs.lsr |= ch >> 8;
+ uart_check_rlsi(uart);
+ }
+ }
+ uart_check_rdi(uart);
+}
+
+/* Called when a break sequence is about to start. It stops receiveing
+ * characters and schedules the uart_recv_break to send the break */
+void uart_recv_break_start(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ uart->istat.receiveing = 0;
+ uart->istat.recv_break = 1;
+
+ SCHED_FIND_REMOVE(uart_recv_char, uart);
+
+ if(uart->vapi_id && (uart->vapi_buf_head_ptr != uart->vapi_buf_tail_ptr))
+ uart_vapi_cmd(uart);
+
+ SCHED_ADD(uart_recv_break, uart,
+ UART_BREAK_COUNT * uart->vapi.char_clks * UART_CLOCK_DIVIDER);
+}
+
+/* Stops sending breaks and starts receiveing characters */
+void uart_recv_break_stop(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ uart->istat.recv_break = 0;
+ SCHED_FIND_REMOVE(uart_recv_break, dat);
+}
+
+/* Receives a break */
+void uart_recv_break(void *dat)
+{
+ struct dev_16450 *uart = dat;
+ unsigned lsr = UART_LSR_BREAK | UART_LSR_RXERR | UART_LSR_RDRDY;
+
+ uart_add_char(uart, lsr << 8);
+}
+
+/* Moves a character from the serial register to the RX FIFO */
+void uart_recv_char(void *dat)
+{
+ struct dev_16450 *uart = dat;
+ uint16_t char_to_add;
+
+ /* Set unused character bits to zero and allow lsr register in fifo */
+ char_to_add = uart->iregs.rxser & (((1 << ((uart->regs.lcr & 3) + 5)) - 1) | 0xff00);
+
+ TRACE("Receiving 0x%02"PRIx16"'%c' via UART at %"PRIxADDR"\n",
+ char_to_add, (char)char_to_add, uart->baseaddr);
+ PRINTF ("%c", (char)char_to_add);
+
+ if (uart->regs.mcr & UART_MCR_LOOP) {
+ uart->iregs.rxser = uart->iregs.loopback;
+ uart->istat.receiveing = 1;
+ SCHED_ADD(uart_recv_char, uart, uart->char_clks * UART_CLOCK_DIVIDER);
+ } else {
+ uart->istat.receiveing = 0;
+ uart_sched_recv_check(uart);
+ if(uart->vapi_id && (uart->vapi_buf_head_ptr != uart->vapi_buf_tail_ptr))
+ SCHED_ADD(uart_vapi_cmd, uart, 0);
+ }
+
+ uart_add_char(uart, char_to_add);
+}
+
+/* Checks if there is a character waiting to be received */
+void uart_check_char(void *dat)
+{
+ struct dev_16450 *uart = dat;
+ uint8_t buffer;
+ int retval;
+
+ /* Check if there is something waiting, and put it into rxser */
+ retval = channel_read(uart->channel, (char *)&buffer, 1);
+ if(retval > 0) {
+ TRACE("Shifting 0x%02"PRIx8" (`%c') into shift reg\n", buffer, buffer);
+ uart->iregs.rxser = buffer;
+ uart->istat.receiveing = 1;
+ SCHED_ADD(uart_recv_char, uart, uart->char_clks * UART_CLOCK_DIVIDER);
+ return;
+ }
+
+ if(!retval) {
+ SCHED_ADD(uart_check_char, uart, UART_FGETC_SLOWDOWN * UART_CLOCK_DIVIDER);
+ return;
+ }
+
+ if(retval < 0)
+ perror(uart->channel_str);
+}
+
+static void uart_sched_recv_check(struct dev_16450 *uart)
+{
+ if(!uart->vapi_id)
+ SCHED_ADD(uart_check_char, uart, UART_FGETC_SLOWDOWN * UART_CLOCK_DIVIDER);
+}
+
+/*----------------------------------------------------[ UART I/O handling ]---*/
+/* Set a specific UART register with value. */
+void uart_write_byte(oraddr_t addr, uint8_t value, void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ if (uart->regs.lcr & UART_LCR_DLAB) {
+ switch (addr) {
+ case UART_DLL:
+ uart->regs.dll = value;
+ uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
+ TRACE("\tSetting char_clks to %li (%02x, %02x, %02x)\n", uart->char_clks,
+ uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
+ return;
+ case UART_DLH:
+ TRACE("Setting dlh with %"PRIx8"\n", value);
+ uart->regs.dlh = value;
+ return;
+ }
+ }
+
+ switch (addr) {
+ case UART_TXBUF:
+ TRACE("Adding %"PRIx8" to TX FIFO (fill %i)\n", value,
+ uart->istat.txbuf_full);
+ uart->regs.lsr &= ~UART_LSR_TXBUFE;
+ if (uart->istat.txbuf_full < uart->fifo_len) {
+ uart->regs.txbuf[uart->istat.txbuf_head] = value;
+ uart->istat.txbuf_head = (uart->istat.txbuf_head + 1) % uart->fifo_len;
+ if(!uart->istat.txbuf_full++ && (uart->regs.lsr & UART_LSR_TXSERE))
+ SCHED_ADD(uart_tx_send, uart, 0);
+ } else
+ uart->regs.txbuf[uart->istat.txbuf_head] = value;
+
+ uart_clear_int(uart, UART_IIR_THRI);
+ break;
+ case UART_FCR:
+ TRACE("Setting FCR reg with %"PRIx8"\n", value);
+ uart->regs.fcr = value & UART_VALID_FCR;
+ if ((uart->fifo_len == 1 && (value & UART_FCR_FIE))
+ || (uart->fifo_len != 1 && !(value & UART_FCR_FIE)))
+ value |= UART_FCR_RRXFI | UART_FCR_RTXFI;
+ uart->fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
+ if (value & UART_FCR_RTXFI) {
+ uart->istat.txbuf_head = uart->istat.txbuf_tail = 0;
+ uart->istat.txbuf_full = 0;
+ uart->regs.lsr |= UART_LSR_TXBUFE;
+
+ /* For FIFO-mode only, THRE interrupt is set when THR and FIFO are empty
+ */
+ if(uart->fifo_len == 16)
+ SCHED_ADD(uart_int_thri, uart, 0);
+
+ SCHED_FIND_REMOVE(uart_tx_send, uart);
+ }
+ if (value & UART_FCR_RRXFI) {
+ uart->istat.rxbuf_head = uart->istat.rxbuf_tail = 0;
+ uart->istat.rxbuf_full = 0;
+ uart->regs.lsr &= ~UART_LSR_RDRDY;
+ uart_clear_int(uart, UART_IIR_RDI);
+ uart_clear_int(uart, UART_IIR_CTI);
+ }
+ break;
+ case UART_IER:
+ uart->regs.ier = value & UART_VALID_IER;
+ TRACE("Enabling 0x%02x interrupts with 0x%x interrupts pending\n",
+ value, uart->istat.ints);
+ SCHED_ADD(uart_next_int, uart, 0);
+ break;
+ case UART_LCR:
+ TRACE("Setting LCR reg with %"PRIx8"\n", value);
+ if((uart->regs.lcr & UART_LCR_SBC) != (value & UART_LCR_SBC)) {
+ if((value & UART_LCR_SBC) && !(uart->regs.lsr & UART_LSR_TXSERE)) {
+ /* Schedule a job to send the break char */
+ SCHED_FIND_REMOVE(uart_char_clock, uart);
+ SCHED_ADD(uart_send_break, uart, 0);
+ }
+ if(!(value & UART_LCR_SBC) && !(uart->regs.lsr & UART_LSR_TXSERE)) {
+ /* Schedule a job to start sending characters */
+ SCHED_ADD(uart_tx_send, uart, 0);
+ /* Remove the uart_send_break job just in case it has not run yet */
+ SCHED_FIND_REMOVE(uart_char_clock, uart);
+ }
+ }
+ uart->regs.lcr = value & UART_VALID_LCR;
+ uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
+ break;
+ case UART_MCR:
+ TRACE("Setting MCR reg with %"PRIx8"\n", value);
+ uart->regs.mcr = value & UART_VALID_MCR;
+ uart_loopback(uart);
+ break;
+ case UART_SCR:
+ TRACE("Setting SCR reg with %"PRIx8"\n", value);
+ uart->regs.scr = value;
+ break;
+ default:
+ TRACE("write out of range (addr %"PRIxADDR")\n", addr);
+ }
+}
+
+/* Read a specific UART register. */
+uint8_t uart_read_byte(oraddr_t addr, void *dat)
+{
+ struct dev_16450 *uart = dat;
+ uint8_t value = 0;
+
+ if (uart->regs.lcr & UART_LCR_DLAB) {
+ switch (addr) {
+ case UART_DLL:
+ value = uart->regs.dll;
+ TRACE("reading DLL = %"PRIx8"\n", value);
+ return value;
+ case UART_DLH:
+ value = uart->regs.dlh;
+ TRACE("reading DLH = %"PRIx8"\n", value);
+ return value;
+ }
+ }
+
+ switch (addr) {
+ case UART_RXBUF:
+ { /* Print out FIFO for debugging */
+ int i;
+ TRACE("(%i/%i, %i, %i:", uart->istat.rxbuf_full, uart->fifo_len,
+ uart->istat.rxbuf_head, uart->istat.rxbuf_tail);
+ for (i = 0; i < uart->istat.rxbuf_full; i++)
+ TRACE("%02x ",
+ uart->regs.rxbuf[(uart->istat.rxbuf_tail + i) % uart->fifo_len]);
+ TRACE(")\n");
+ }
+ if (uart->istat.rxbuf_full) {
+ value = uart->regs.rxbuf[uart->istat.rxbuf_tail];
+ uart->istat.rxbuf_tail = (uart->istat.rxbuf_tail + 1) % uart->fifo_len;
+ uart->istat.rxbuf_full--;
+ TRACE("Reading %"PRIx8" out of RX FIFO\n", value);
+ } else
+ TRACE("Trying to read out of RX FIFO but it's empty!\n");
+
+ uart_clear_int(uart, UART_IIR_RDI);
+ uart_clear_int(uart, UART_IIR_CTI);
+ SCHED_FIND_REMOVE(uart_int_cti, uart);
+
+ if(uart->istat.rxbuf_full) {
+ uart->regs.lsr |= UART_LSR_RDRDY | uart->regs.rxbuf[uart->istat.rxbuf_tail] >> 8;
+ SCHED_ADD(uart_int_cti, uart,
+ uart->char_clks * UART_CHAR_TIMEOUT * UART_CLOCK_DIVIDER);
+ /* Since we're not allowed to raise interrupts from read/write functions
+ * schedule them to run just after we have executed this read
+ * instruction. */
+ SCHED_ADD(uart_check_rlsi, uart, 0);
+ SCHED_ADD(uart_check_rdi, uart, 0);
+ } else {
+ uart->regs.lsr &= ~UART_LSR_RDRDY;
+ }
+ break;
+ case UART_IER:
+ value = uart->regs.ier & UART_VALID_IER;
+ TRACE("reading IER = %"PRIx8"\n", value);
+ break;
+ case UART_IIR:
+ value = (uart->regs.iir & UART_VALID_IIR) | 0xc0;
+ /* Only clear the thri interrupt if it is the one we are repporting */
+ if(uart->regs.iir == UART_IIR_THRI)
+ uart_clear_int(uart, UART_IIR_THRI);
+ TRACE("reading IIR = %"PRIx8"\n", value);
+ break;
+ case UART_LCR:
+ value = uart->regs.lcr & UART_VALID_LCR;
+ TRACE("reading LCR = %"PRIx8"\n", value);
+ break;
+ case UART_MCR:
+ value = 0;
+ TRACE("reading MCR = %"PRIx8"\n", value);
+ break;
+ case UART_LSR:
+ value = uart->regs.lsr & UART_VALID_LSR;
+ uart->regs.lsr &=
+ ~(UART_LSR_OVRRUN | UART_LSR_BREAK | UART_LSR_PARITY
+ | UART_LSR_FRAME | UART_LSR_RXERR);
+ /* Clear potentially pending RLSI interrupt */
+ uart_clear_int(uart, UART_IIR_RLSI);
+ TRACE("reading LSR = %"PRIx8"\n", value);
+ break;
+ case UART_MSR:
+ value = uart->regs.msr & UART_VALID_MSR;
+ uart->regs.msr = 0;
+ uart_clear_int(uart, UART_IIR_MSI);
+ uart_loopback(uart);
+ TRACE("reading MSR = %"PRIx8"\n", value);
+ break;
+ case UART_SCR:
+ value = uart->regs.scr;
+ TRACE("reading SCR = %"PRIx8"\n", value);
+ break;
+ default:
+ TRACE("read out of range (addr %"PRIxADDR")\n", addr);
+ }
+ return value;
+}
+
+/*--------------------------------------------------------[ VAPI handling ]---*/
+/* Decodes the read vapi command */
+static void uart_vapi_cmd(void *dat)
+{
+ struct dev_16450 *uart = dat;
+ int received = 0;
+
+ while (!received) {
+ if (uart->vapi_buf_head_ptr != uart->vapi_buf_tail_ptr) {
+ unsigned long data = uart->vapi_buf[uart->vapi_buf_tail_ptr];
+ TRACE("\tHandling: %08lx (%i,%i)\n", data, uart->vapi_buf_head_ptr,
+ uart->vapi_buf_tail_ptr);
+ uart->vapi_buf_tail_ptr = (uart->vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
+ switch (data >> 24) {
+ case 0x00:
+ uart->vapi.lcr = (data >> 8) & 0xff;
+ /* Put data into rx fifo */
+ uart->iregs.rxser = data & 0xff;
+ uart->vapi.char_clks = char_clks (uart->vapi.dll, uart->vapi.dlh, uart->vapi.lcr);
+ if((uart->vapi.lcr & ~UART_LCR_SBC) != (uart->regs.lcr & ~UART_LCR_SBC)
+ || uart->vapi.char_clks != uart->char_clks
+ || uart->vapi.skew < -MAX_SKEW || uart->vapi.skew > MAX_SKEW) {
+ if((uart->vapi.lcr & ~UART_LCR_SBC) != (uart->regs.lcr & ~UART_LCR_SBC))
+ WARN("unmatched VAPI (%02"PRIx8") and uart (%02"PRIx8") modes.\n",
+ uart->vapi.lcr & ~UART_LCR_SBC, uart->regs.lcr & ~UART_LCR_SBC);
+ if(uart->vapi.char_clks != uart->char_clks) {
+ WARN("unmatched VAPI (%li) and uart (%li) char clocks.\n",
+ uart->vapi.char_clks, uart->char_clks);
+ WARN("VAPI: lcr: %02"PRIx8", dll: %02"PRIx8", dlh: %02"PRIx8"\n",
+ uart->vapi.lcr, uart->vapi.dll, uart->vapi.dlh);
+ WARN("UART: lcr: %02"PRIx8", dll: %02"PRIx8", dlh: %02"PRIx8"\n",
+ uart->regs.lcr, uart->regs.dll, uart->vapi.dlh);
+ }
+ if(uart->vapi.skew < -MAX_SKEW || uart->vapi.skew > MAX_SKEW)
+ WARN("VAPI skew is beyond max: %i\n", uart->vapi.skew);
+ /* Set error bits */
+ uart->iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
+ if(uart->regs.lcr & UART_LCR_PARITY)
+ uart->iregs.rxser |= UART_LSR_PARITY << 8;
+ }
+ if(!uart->istat.recv_break) {
+ uart->istat.receiveing = 1;
+ SCHED_ADD(uart_recv_char, uart, uart->char_clks * UART_CLOCK_DIVIDER);
+ }
+ received = 1;
+ break;
+ case 0x01:
+ uart->vapi.dll = (data >> 0) & 0xff;
+ uart->vapi.dlh = (data >> 8) & 0xff;
+ break;
+ case 0x02:
+ uart->vapi.lcr = (data >> 8) & 0xff;
+ break;
+ case 0x03:
+ uart->vapi.skew = (signed short)(data & 0xffff);
+ break;
+ case 0x04:
+ if((data >> 16) & 1) {
+ /* If data & 0xffff is 0 then set the break imediatly and handle the
+ * following commands as appropriate */
+ if(!(data & 0xffff))
+ uart_recv_break_start(uart);
+ else
+ /* Schedule a job to start sending breaks */
+ SCHED_ADD(uart_recv_break_start, uart,
+ (data & 0xffff) * UART_CLOCK_DIVIDER);
+ } else {
+ /* If data & 0xffff is 0 then release the break imediatly and handle
+ * the following commands as appropriate */
+ if(!(data & 0xffff))
+ uart_recv_break_stop(uart);
+ else
+ /* Schedule a job to stop sending breaks */
+ SCHED_ADD(uart_recv_break_stop, uart,
+ (data & 0xffff) * UART_CLOCK_DIVIDER);
+ }
+ break;
+ default:
+ WARN("WARNING: Invalid vapi command %02lx\n", data >> 24);
+ break;
+ }
+ } else break;
+ }
+}
+
+/* Function that handles incoming VAPI data. */
+void uart_vapi_read (unsigned long id, unsigned long data, void *dat)
+{
+ struct dev_16450 *uart = dat;
+ TRACE("UART: id %08lx, data %08lx\n", id, data);
+ uart->vapi_buf[uart->vapi_buf_head_ptr] = data;
+ uart->vapi_buf_head_ptr = (uart->vapi_buf_head_ptr + 1) % UART_VAPI_BUF_LEN;
+ if (uart->vapi_buf_tail_ptr == uart->vapi_buf_head_ptr) {
+ fprintf (stderr, "FATAL: uart VAPI buffer to small.\n");
+ exit (1);
+ }
+ if(!uart->istat.receiveing)
+ uart_vapi_cmd(uart);
+}
+
+/*--------------------------------------------------------[ Sim callbacks ]---*/
+/* Reset. It initializes all registers of all UART devices to zero values,
+ * (re)opens all RX/TX file streams and places devices in memory address
+ * space. */
+void uart_reset(void *dat)
+{
+ struct dev_16450 *uart = dat;
+
+ if(uart->vapi_id) {
+ vapi_install_handler(uart->vapi_id, uart_vapi_read, dat);
+ } else if (uart->channel_str && uart->channel_str[0]) { /* Try to create stream. */
+ if(uart->channel)
+ channel_close(uart->channel);
+ else
+ uart->channel = channel_init(uart->channel_str);
+ if(channel_open(uart->channel) < 0) {
+ WARN ("WARNING: problem with channel \"%s\" detected.\n", uart->channel_str);
+ } else if (config.sim.verbose)
+ PRINTF("UART at 0x%"PRIxADDR"\n", uart->baseaddr);
+ } else {
+ WARN ("WARNING: UART at %"PRIxADDR" has no vapi nor channel specified\n",
+ uart->baseaddr);
+ }
+
+ if (uart->uart16550)
+ uart->fifo_len = 16;
+ else
+ uart->fifo_len = 1;
+
+ uart->istat.rxbuf_head = uart->istat.rxbuf_tail = 0;
+ uart->istat.txbuf_head = uart->istat.txbuf_tail = 0;
+
+ uart->istat.txbuf_full = uart->istat.rxbuf_full = 0;
+
+ uart->char_clks = 0;
+
+ uart->iregs.txser = 0;
+ uart->iregs.rxser = 0;
+ uart->iregs.loopback = 0;
+ uart->istat.receiveing = 0;
+ uart->istat.recv_break = 0;
+ uart->istat.ints = 0;
+
+ memset(uart->regs.txbuf, 0, sizeof(uart->regs.txbuf));
+ memset(uart->regs.rxbuf, 0, sizeof(uart->regs.rxbuf));
+
+ uart->regs.dll = 0;
+ uart->regs.dlh = 0;
+ uart->regs.ier = 0;
+ uart->regs.iir = UART_IIR_NO_INT;
+ uart->regs.fcr = 0;
+ uart->regs.lcr = UART_LCR_RESET;
+ uart->regs.mcr = 0;
+ uart->regs.lsr = UART_LSR_TXBUFE | UART_LSR_TXSERE;
+ uart->regs.msr = 0;
+ uart->regs.scr = 0;
+
+ uart->vapi.skew = 0;
+ uart->vapi.lcr = 0;
+ uart->vapi.dll = 0;
+ uart->vapi.char_clks = 0;
+
+ uart->vapi_buf_head_ptr = 0;
+ uart->vapi_buf_tail_ptr = 0;
+ memset(uart->vapi_buf, 0, sizeof(uart->vapi_buf));
+
+ uart_sched_recv_check(uart);
+}
+
+/* Print register values on stdout. */
+void uart_status(void *dat)
+{
+ struct dev_16450 *uart = dat;
+ int i;
+
+ PRINTF("\nUART visible registers at 0x%"PRIxADDR":\n", uart->baseaddr);
+ PRINTF("RXBUF: ");
+ for (i = uart->istat.rxbuf_head; i != uart->istat.rxbuf_tail; i = (i + 1) % uart->fifo_len)
+ PRINTF (" %.2x", uart->regs.rxbuf[i]);
+ PRINTF("TXBUF: ");
+ for (i = uart->istat.txbuf_head; i != uart->istat.txbuf_tail; i = (i + 1) % uart->fifo_len)
+ PRINTF (" %.2x", uart->regs.txbuf[i]);
+ PRINTF("\n");
+ PRINTF("DLL : %.2x DLH : %.2x\n", uart->regs.dll, uart->regs.dlh);
+ PRINTF("IER : %.2x IIR : %.2x\n", uart->regs.ier, uart->regs.iir);
+ PRINTF("LCR : %.2x MCR : %.2x\n", uart->regs.lcr, uart->regs.mcr);
+ PRINTF("LSR : %.2x MSR : %.2x\n", uart->regs.lsr, uart->regs.msr);
+ PRINTF("SCR : %.2x\n", uart->regs.scr);
+
+ PRINTF("\nInternal registers (sim debug):\n");
+ PRINTF("RXSER: %.2"PRIx16" TXSER: %.2"PRIx8"\n", uart->iregs.rxser,
+ uart->iregs.txser);
+
+ PRINTF("\nInternal status (sim debug):\n");
+ PRINTF("char_clks: %ld\n", uart->char_clks);
+ PRINTF("rxbuf_full: %d txbuf_full: %d\n", uart->istat.rxbuf_full, uart->istat.txbuf_full);
+ PRINTF("Using IRQ%i\n", uart->irq);
+ if (uart->vapi_id)
+ PRINTF ("Connected to vapi ID=%lx\n\n", uart->vapi_id);
+ /* TODO: replace by a channel_status
+ else
+ PRINTF("RX fs: %p TX fs: %p\n\n", uart->rxfs, uart->txfs);
+ */
+}
+
+/*---------------------------------------------------[ UART configuration ]---*/
+void uart_baseaddr(union param_val val, void *dat)
+{
+ struct dev_16450 *uart = dat;
+ uart->baseaddr = val.addr_val;
+}
+
+void uart_jitter(union param_val val, void *dat)
+{
+ struct dev_16450 *uart = dat;
+ uart->jitter = val.int_val;
+}
+
+void uart_irq(union param_val val, void *dat)
+{
+ struct dev_16450 *uart = dat;
+ uart->irq = val.int_val;
+}
+
+void uart_16550(union param_val val, void *dat)
+{
+ struct dev_16450 *uart = dat;
+ uart->uart16550 = val.int_val;
+}
+
+void uart_channel(union param_val val, void *dat)
+{
+ struct dev_16450 *uart = dat;
+ if(!(uart->channel_str = strdup(val.str_val))) {
+ fprintf(stderr, "Peripheral 16450: Run out of memory\n");
+ exit(-1);
+ }
+}
+
+void uart_newway(union param_val val, void *dat)
+{
+ CONFIG_ERROR(" txfile and rxfile and now obsolete.\n\tUse 'channel = \"file:rxfile,txfile\"' instead.");
+ exit(1);
+}
+
+void uart_vapi_id(union param_val val, void *dat)
+{
+ struct dev_16450 *uart = dat;
+ uart->vapi_id = val.int_val;
+}
+
+void uart_enabled(union param_val val, void *dat)
+{
+ struct dev_16450 *uart = dat;
+ uart->enabled = val.int_val;
+}
+
+void *uart_sec_start(void)
+{
+ struct dev_16450 *new = malloc(sizeof(struct dev_16450));
+
+ if(!new) {
+ fprintf(stderr, "Peripheral 16450: Run out of memory\n");
+ exit(-1);
+ }
+
+ new->enabled = 1;
+ new->channel_str = NULL;
+ new->channel = NULL;
+ new->vapi_id = 0;
+
+ return new;
+}
+
+void uart_sec_end(void *dat)
+{
+ struct dev_16450 *uart = dat;
+ struct mem_ops ops;
+
+ if(!uart->enabled) {
+ free(dat);
+ return;
+ }
+
+ memset(&ops, 0, sizeof(struct mem_ops));
+
+ ops.readfunc8 = uart_read_byte;
+ ops.writefunc8 = uart_write_byte;
+ ops.read_dat8 = dat;
+ ops.write_dat8 = dat;
+
+ /* FIXME: What should these be? */
+ ops.delayr = 2;
+ ops.delayw = 2;
+
+ reg_mem_area(uart->baseaddr, UART_ADDR_SPACE, 0, &ops);
+
+ reg_sim_reset(uart_reset, dat);
+ reg_sim_stat(uart_status, dat);
+}
+
+void reg_uart_sec(void)
+{
+ struct config_section *sec = reg_config_sec("uart", uart_sec_start,
+ uart_sec_end);
+
+ reg_config_param(sec, "baseaddr", paramt_addr, uart_baseaddr);
+ reg_config_param(sec, "enabled", paramt_int, uart_enabled);
+ reg_config_param(sec, "irq", paramt_int, uart_irq);
+ reg_config_param(sec, "16550", paramt_int, uart_16550);
+ reg_config_param(sec, "jitter", paramt_int, uart_jitter);
+ reg_config_param(sec, "channel", paramt_str, uart_channel);
+ reg_config_param(sec, "txfile", paramt_str, uart_newway);
+ reg_config_param(sec, "rxfile", paramt_str, uart_newway);
+ reg_config_param(sec, "vapi_id", paramt_int, uart_vapi_id);
+}
Index: mc.c
===================================================================
--- mc.c (nonexistent)
+++ mc.c (revision 1765)
@@ -0,0 +1,346 @@
+/* mc.c -- Simulation of Memory Controller
+ Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* Enable memory controller, via:
+ section mc
+ enable = 1
+ POC = 0x13243545
+ end
+
+ Limitations:
+ - memory refresh is not simulated
+*/
+
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "mc.h"
+#include "abstract.h"
+#include "sim-config.h"
+#include "debug.h"
+
+DEFAULT_DEBUG_CHANNEL(mc);
+
+struct mc_area {
+ struct dev_memarea *mem;
+ unsigned int cs;
+ int mc;
+ struct mc_area *next;
+};
+
+struct mc {
+ uint32_t csr;
+ uint32_t poc;
+ uint32_t ba_mask;
+ uint32_t csc[N_CE];
+ uint32_t tms[N_CE];
+ oraddr_t baseaddr;
+ int enabled;
+
+ /* Index of this memory controler amongst all the memory controlers */
+ int index;
+ /* List of memory devices under this mc's control */
+ struct mc_area *mc_areas;
+
+ struct mc *next;
+};
+
+static struct mc *mcs = NULL;
+
+/* List used to temporarily hold memory areas registered with the mc, while the
+ * mc configureation has not been loaded */
+static struct mc_area *mc_areas = NULL;
+
+void set_csc_tms (int cs, uint32_t csc, uint32_t tms, struct mc *mc)
+{
+ struct mc_area *cur = mc->mc_areas;
+
+ while (cur) {
+ if (cur->cs == cs) {
+ /* FIXME: No peripheral should _ever_ acess a dev_memarea structure
+ * directly */
+ TRACE("Remapping %"PRIxADDR"-%"PRIxADDR" to %"PRIxADDR"-%"PRIxADDR"\n",
+ cur->mem->addr_compare,
+ cur->mem->addr_compare | cur->mem->size_mask,
+ (csc >> MC_CSC_SEL_OFFSET) << 22,
+ ((csc >> MC_CSC_SEL_OFFSET) << 22) | cur->mem->size_mask);
+
+ cur->mem->addr_mask = mc->ba_mask << 22;
+ cur->mem->addr_compare = ((csc >> MC_CSC_SEL_OFFSET) /* & 0xff*/) << 22;
+ set_mem_valid(cur->mem, (csc >> MC_CSC_EN_OFFSET) & 0x01);
+
+ if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC) {
+ adjust_rw_delay(cur->mem, (tms & 0xff) + ((tms >> 8) & 0x0f),
+ ((tms >> 12) & 0x0f) + ((tms >> 16) & 0x0f) + ((tms >> 20) & 0x3f));
+ } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SDRAM) {
+ adjust_rw_delay(cur->mem, 3 + ((tms >> 4) & 0x03),
+ 3 + ((tms >> 4) & 0x03));
+ } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SSRAM) {
+ adjust_rw_delay(cur->mem, 2, 2);
+ } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SYNC) {
+ adjust_rw_delay(cur->mem, 2, 2);
+ }
+ return;
+ }
+ cur = cur->next;
+ }
+}
+
+/* Set a specific MC register with value. */
+void mc_write_word(oraddr_t addr, uint32_t value, void *dat)
+{
+ struct mc *mc = dat;
+ int chipsel;
+
+ TRACE("mc_write_word(%"PRIxADDR",%08"PRIx32")\n", addr, value);
+
+ switch (addr) {
+ case MC_CSR:
+ mc->csr = value;
+ break;
+ case MC_POC:
+ WARN("warning: write to MC's POC register!");
+ break;
+ case MC_BA_MASK:
+ mc->ba_mask = value & MC_BA_MASK_VALID;
+ for (chipsel = 0; chipsel < N_CE; chipsel++)
+ set_csc_tms (chipsel, mc->csc[chipsel], mc->tms[chipsel], mc);
+ break;
+ default:
+ if (addr >= MC_CSC(0) && addr <= MC_TMS(N_CE - 1)) {
+ addr -= MC_CSC(0);
+ if ((addr >> 2) & 1)
+ mc->tms[addr >> 3] = value;
+ else
+ mc->csc[addr >> 3] = value;
+
+ set_csc_tms (addr >> 3, mc->csc[addr >> 3], mc->tms[addr >> 3], mc);
+ break;
+ } else
+ TRACE("write out of range (addr %"PRIxADDR")\n", addr + mc->baseaddr);
+ }
+}
+
+/* Read a specific MC register. */
+uint32_t mc_read_word(oraddr_t addr, void *dat)
+{
+ struct mc *mc = dat;
+ uint32_t value = 0;
+
+ TRACE("mc_read_word(%"PRIxADDR")", addr);
+
+ switch (addr) {
+ case MC_CSR:
+ value = mc->csr;
+ break;
+ case MC_POC:
+ value = mc->poc;
+ break;
+ case MC_BA_MASK:
+ value = mc->ba_mask;
+ break;
+ default:
+ if (addr >= MC_CSC(0) && addr <= MC_TMS(N_CE - 1)) {
+ addr -= MC_CSC(0);
+ if ((addr >> 2) & 1)
+ value = mc->tms[addr >> 3];
+ else
+ value = mc->csc[addr >> 3];
+ } else
+ TRACE(" read out of range (addr %"PRIxADDR")\n", addr + mc->baseaddr);
+ break;
+ }
+ TRACE(" value(%"PRIx32")\n", value);
+ return value;
+}
+
+/* Read POC register and init memory controler regs. */
+void mc_reset(void *dat)
+{
+ struct mc *mc = dat;
+ struct mc_area *cur, *prev, *tmp;
+
+ PRINTF("Resetting memory controller.\n");
+
+ memset(mc->csc, 0, sizeof(mc->csc));
+ memset(mc->tms, 0, sizeof(mc->tms));
+
+ mc->csr = 0;
+ mc->ba_mask = 0;
+
+ /* Set CS0 */
+ mc->csc[0] = (((mc->poc & 0x0c) >> 2) << MC_CSC_MEMTYPE_OFFSET) | ((mc->poc & 0x03) << MC_CSC_BW_OFFSET) | 1;
+
+ if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC) {
+ mc->tms[0] = MC_TMS_ASYNC_VALID;
+ } else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SDRAM) {
+ mc->tms[0] = MC_TMS_SDRAM_VALID;
+ } else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SSRAM) {
+ mc->tms[0] = MC_TMS_SSRAM_VALID;
+ } else if ((mc->csc[0] >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SYNC) {
+ mc->tms[0] = MC_TMS_SYNC_VALID;
+ }
+
+ /* Grab control over all the devices we are destined to control */
+ cur = mc_areas;
+ prev = NULL;
+ while (cur) {
+ if (cur->mc == mc->index) {
+ if (prev) prev->next = cur->next;
+ else mc_areas = cur->next;
+ prev = cur;
+ tmp = cur->next;
+ cur->next = mc->mc_areas;
+ mc->mc_areas = cur;
+ cur = tmp;
+ } else {
+ prev = cur;
+ cur = cur->next;
+ }
+ }
+
+ for (cur = mc->mc_areas; cur; cur = cur->next)
+ set_mem_valid(cur->mem, 0);
+
+ set_csc_tms (0, mc->csc[0], mc->tms[0], mc);
+}
+
+void mc_status(void *dat)
+{
+ struct mc *mc = dat;
+ int i;
+
+ PRINTF( "\nMemory Controller at 0x%"PRIxADDR":\n", mc->baseaddr );
+ PRINTF( "POC: 0x%"PRIx32"\n", mc->poc );
+ PRINTF( "BAS: 0x%"PRIx32"\n", mc->ba_mask );
+ PRINTF( "CSR: 0x%"PRIx32"\n", mc->csr );
+
+ for (i=0; icsc[i], mc->tms[i]);
+ }
+}
+
+/*--------------------------------------------[ Peripheral<->MC interface ]---*/
+/* Registers some memory to be under the memory controllers control */
+void mc_reg_mem_area(struct dev_memarea *mem, unsigned int cs, int mc)
+{
+ struct mc_area *new;
+
+ if(!(new = malloc(sizeof(struct mc_area)))) {
+ fprintf(stderr, "Out-of-memory\n");
+ exit(-1);
+ }
+ new->cs = cs;
+ new->mem = mem;
+ new->mc = mc;
+
+ new->next = mc_areas;
+ mc_areas = new;
+}
+
+/*-----------------------------------------------------[ MC configuration ]---*/
+void mc_enabled(union param_val val, void *dat)
+{
+ struct mc *mc = dat;
+ mc->enabled = val.int_val;
+}
+
+void mc_baseaddr(union param_val val, void *dat)
+{
+ struct mc *mc = dat;
+ mc->baseaddr = val.addr_val;
+}
+
+void mc_POC(union param_val val, void *dat)
+{
+ struct mc *mc = dat;
+ mc->poc = val.int_val;
+}
+
+void mc_index(union param_val val, void *dat)
+{
+ struct mc *mc = dat;
+ mc->index = val.int_val;
+}
+
+void *mc_sec_start(void)
+{
+ struct mc *new = malloc(sizeof(struct mc));
+
+ if(!new) {
+ fprintf(stderr, "Peripheral MC: Run out of memory\n");
+ exit(-1);
+ }
+
+ new->index = 0;
+ new->enabled = 0;
+ new->mc_areas = NULL;
+
+ return new;
+}
+
+void mc_sec_end(void *dat)
+{
+ struct mc *mc = dat;
+ struct mem_ops ops;
+
+ if(!mc->enabled) {
+ free(dat);
+ return;
+ }
+
+ /* FIXME: Check to see that the index given to this mc is unique */
+
+ mc->next = mcs;
+ mcs = mc;
+
+ memset(&ops, 0, sizeof(struct mem_ops));
+
+ ops.readfunc32 = mc_read_word;
+ ops.writefunc32 = mc_write_word;
+ ops.write_dat32 = dat;
+ ops.read_dat32 = dat;
+
+ /* FIXME: Correct delays? */
+ ops.delayr = 2;
+ ops.delayw = 2;
+
+ reg_mem_area(mc->baseaddr, MC_ADDR_SPACE, 1, &ops);
+ reg_sim_reset(mc_reset, dat);
+ reg_sim_stat(mc_status, dat);
+}
+
+void reg_mc_sec(void)
+{
+ struct config_section *sec = reg_config_sec("mc", mc_sec_start, mc_sec_end);
+
+ reg_config_param(sec, "enabled", paramt_int, mc_enabled);
+ reg_config_param(sec, "baseaddr", paramt_addr, mc_baseaddr);
+ reg_config_param(sec, "POC", paramt_int, mc_POC);
+ reg_config_param(sec, "index", paramt_int, mc_index);
+}
mc.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: atadevice.c
===================================================================
--- atadevice.c (nonexistent)
+++ atadevice.c (revision 1765)
@@ -0,0 +1,554 @@
+/*
+ atadevice.c -- ATA Device simulation
+ Simulates a harddisk, using a local streams.
+ Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "abstract.h"
+
+#include "atadevice.h"
+#include "atacmd.h"
+#include "sim-config.h"
+#include "atadevice_cmdi.h"
+
+#include "debug.h"
+
+DEFAULT_DEBUG_CHANNEL(ata);
+
+/*
+ mandatory commands:
+ - execute device diagnostics (done)
+ - flush cache
+ - identify device (done)
+ - initialize device parameters (done)
+ - read dma
+ - read multiple
+ - read sector(s) (done)
+ - read verify sector(s)
+ - seek
+ - set features
+ - set multiple mode
+ - write dma
+ - write multiple
+ - write sector(s)
+
+
+ optional commands:
+ - download microcode
+ - nop
+ - read buffer
+ - write buffer
+
+
+ prohibited commands:
+ - device reset
+*/
+
+
+/*
+ D E V I C E S _ I N I T
+*/
+void ata_devices_init(ata_devices *devices)
+{
+ ata_device_init(&devices->device0, 0);
+
+ if (devices->device0.type)
+ ata_device_init(&devices->device1, ATA_DHR_DEV);
+ else
+ ata_device_init(&devices->device1, 0);
+}
+
+
+void ata_device_init(ata_device *device, int dev)
+{
+ /* set DeviceID */
+ device->internals.dev = dev;
+
+ /* generate stream for hd_simulation */
+ switch(device->type)
+ {
+ case TYPE_NO_CONNECT:
+ TRACE("ata_device, using type NO_CONNECT.\n");
+ device->stream = NULL;
+ break;
+
+ case TYPE_FILE:
+ TRACE("ata_device, using device type FILE.\n");
+ device->stream = open_file(&device->size, device->file);
+ break;
+
+ case TYPE_LOCAL:
+ TRACE("ata_device, using device type LOCAL.\n");
+ device->stream = open_local();
+ break;
+
+ default:
+ ERR("Illegal device-type. Defaulting to type NO_CONNECT.\n");
+ device->stream = NULL;
+ break;
+ }
+}
+
+/* Use a file to simulate a hard-disk */
+FILE *open_file(unsigned long *size, const char *filename)
+{
+ FILE *fp;
+ unsigned long n;
+
+ // TODO:
+
+ /* check if a file with name 'filename' already exists */
+ if ( !(fp = fopen(filename, "rb+")) )
+ if ( !(fp = fopen(filename, "wb+")) )
+ {
+ ERR( "ata_open_file, cannot open hd-file %s\n", filename );
+ return NULL;
+ }
+ else
+ {
+ /* TODO create a file 'size' large */
+ /* create a file 'size' large */
+ TRACE("ata_device; generating a new hard disk file.\n");
+ TRACE("This may take a while, depending on the requested size.\n");
+ for (n=0; n < (*size << 20); n++)
+ fputc(0, fp);
+ }
+ else /* file already exist */
+ fprintf(stderr, "file %s already exists. Using existing file.\n", filename);
+
+
+ TRACE("requested filesize was: %ld (MBytes).\n", *size);
+
+ /* get the size of the file. This is also the size of the harddisk*/
+ fseek(fp, 0, SEEK_END);
+ *size = ftell(fp);
+
+ TRACE("actual filesize is: %ld (MBytes).\n", *size >> 20);
+
+ return fp;
+}
+
+
+/* Use a the local filesystem as a hard-disk */
+FILE *open_local(void)
+{
+ // TODO:
+ FIXME("Device type LOCAL is not yet supported. Defaulting to device type NO_CONNECT.");
+ return NULL;
+}
+
+
+
+
+/*
+ D E V I C E S _ H W _ R E S E T
+*/
+/* power-on and hardware reset */
+void ata_devices_hw_reset(ata_devices *devices, int reset_signal)
+{
+ /* display debug information */
+ TRACE("ata_devices_hw_reset.\n");
+
+ /* find device 0 */
+ if ( (devices->device0.stream) && (devices->device1.stream) )
+ {
+ /* this one is simple, device0 is device0 */
+
+ /* 1) handle device1 first */
+ ata_device_hw_reset(&devices->device1, reset_signal,
+ 1, /* assert dasp, this is device1 */
+ 0, /* negate pdiag input, no more devices */
+ 0); /* negate dasp input, no more devices */
+
+ /* 2) Then handle device0 */
+ ata_device_hw_reset(&devices->device0, reset_signal,
+ 0,
+ devices->device1.sigs.pdiago,
+ devices->device1.sigs.daspo);
+ }
+ else if (devices->device0.stream)
+ {
+ /* device0 is device0, there's no device1 */
+ ata_device_hw_reset(&devices->device0, reset_signal,
+ 0, /* negate dasp, this is device0 */
+ 0, /* negate pdiag input, there's no device1*/
+ 0); /* negate dasp input, there's no device1 */
+ }
+ else if (devices->device1.stream)
+ {
+ /* device1 is (logical) device0, there's no (physical) device0 */
+ ata_device_hw_reset(&devices->device1, reset_signal,
+ 0, /* negate dasp, this is device0 */
+ 0, /* negate pdiag input, there's no device1*/
+ 0); /* negate dasp input, there's no device1 */
+ }
+ else
+ {
+ /* no devices connected */
+ TRACE("ata_device_hw_reset, no devices connected.\n");
+ }
+}
+
+void ata_device_hw_reset(ata_device *device, int reset_signal,
+ int daspo, int pdiagi, int daspi)
+{
+ /* check ata-device state */
+ if (device->internals.state == ATA_STATE_HW_RST)
+ {
+ if (!reset_signal)
+ {
+ /* hardware reset finished */
+
+ /* set sectors_per_track & heads_per_cylinders */
+ device->internals.sectors_per_track = SECTORS;
+ device->internals.heads_per_cylinder = HEADS;
+
+ /* set device1 input signals */
+ device->sigs.pdiagi = pdiagi;
+ device->sigs.daspi = daspi;
+
+ ata_execute_device_diagnostics_cmd(device);
+
+ /* clear busy bit */
+ device->regs.status &= ~ATA_SR_BSY;
+
+ /* set DRDY bit, when not a PACKET device */
+ if (!device->packet)
+ device->regs.status |= ATA_SR_DRDY;
+
+ /* set new state */
+ device->internals.state = ATA_STATE_IDLE;
+ }
+ }
+ else
+ if (reset_signal)
+ {
+ /* hardware reset signal asserted, stop what we are doing */
+
+ /* negate bus signals */
+ device->sigs.iordy = 0;
+ device->sigs.intrq = 0;
+ device->sigs.dmarq = 0;
+ device->sigs.pdiago = 0;
+ device->sigs.daspo = daspo;
+
+ /* set busy bit */
+ device->regs.status |= ATA_SR_BSY;
+ PRINTF("setting status register BSY 0x%2X\n", device->regs.status);
+
+ /* set new state */
+ device->internals.state = ATA_STATE_HW_RST;
+ }
+}
+
+
+/*
+ D E V I C E S _ D O _ C O N T R O L _ R E G I S T E R
+
+ Handles - software reset
+ - Interrupt enable bit
+*/
+void ata_device_do_control_register(ata_device *device)
+{
+ /* TODO respond to new values of nIEN */
+ /* if device not selected, respond to new values of nIEN & SRST */
+
+ /* check if SRST bit is set */
+ if (device->regs.device_control & ATA_DCR_RST)
+ {
+ if (device->internals.state == ATA_STATE_IDLE)
+ { /* start software reset */
+ /* negate bus signals */
+ device->sigs.pdiago = 0;
+ device->sigs.intrq = 0;
+ device->sigs.iordy = 0;
+ device->sigs.dmarq = 0;
+
+ /* set busy bit */
+ device->regs.status |= ATA_SR_BSY;
+
+ /* set new state */
+ device->internals.state = ATA_STATE_SW_RST;
+
+ /* display debug information */
+ TRACE("ata_device_sw_reset initiated.\n");
+ }
+ }
+ else if (device->internals.state == ATA_STATE_SW_RST)
+ { /* are we doing a software reset ?? */
+ /* SRST bit cleared, end of software reset */
+
+ /*execute device diagnostics */
+ ata_execute_device_diagnostics_cmd(device);
+
+ /* clear busy bit */
+ device->regs.status &= ~ATA_SR_BSY;
+
+ /* set DRDY bit, when not a PACKET device */
+ if (!device->packet)
+ device->regs.status |= ATA_SR_DRDY;
+
+ /* set new state */
+ device->internals.state = ATA_STATE_IDLE;
+
+ /* display debug information */
+ TRACE("ata_device_sw_reset done.\n");
+ }
+ /*
+ We are doing a hardware reset (or similar)
+ ignore command
+ */
+}
+
+
+/*
+ D E V I C E S _ D O _ C O M M A N D _ R E G I S T E R
+*/
+void ata_device_do_command_register(ata_device *device)
+{
+ /* check BSY & DRQ */
+ if ( (device->regs.status & ATA_SR_BSY) || (device->regs.status & ATA_SR_DRQ) )
+ if (device->regs.command != DEVICE_RESET)
+ WARN("ata_device_write, writing a command while BSY or DRQ asserted.");
+
+ /* check if device selected */
+ if ( (device->regs.device_head & ATA_DHR_DEV) == device->internals.dev )
+ ata_device_execute_cmd(device);
+ else
+ {
+ /* if not selected, only respond to EXECUTE DEVICE DIAGNOSTICS */
+ if (device->regs.command == EXECUTE_DEVICE_DIAGNOSTICS)
+ ata_device_execute_cmd(device);
+ }
+}
+
+
+/*
+ D E V I C E S _ R E A D
+*/
+/* Read from devices */
+short ata_devices_read(ata_devices *devices, char adr)
+{
+ ata_device *device;
+
+ /* check for no connected devices */
+ if ( (!devices->device0.stream) && (!devices->device1.stream) )
+ ERR("ata_devices_read, no ata devices connected.\n");
+ else
+ {
+ /* check if both device0 and device1 are connected */
+ if ( (devices->device0.stream) && (devices->device1.stream) )
+ {
+ /* get the current active device */
+ if (devices->device1.regs.device_head & ATA_DHR_DEV)
+ device = &devices->device1;
+ else
+ device = &devices->device0;
+ }
+ else
+ {
+ /* only one device connected */
+ if (devices->device1.stream)
+ device = &devices->device1;
+ else
+ device = &devices->device0;
+ }
+
+ /* return data provided by selected device */
+ switch (adr) {
+ case ATA_ASR :
+ TRACE("alternate_status register read\n");
+ if ( (device->regs.device_head & ATA_DHR_DEV) == device->internals.dev )
+ return device -> regs.status;
+ else
+ {
+ TRACE("device0 responds for device1, asr = 0x00\n");
+ return 0; // return 0 when device0 responds for device1
+ }
+
+ case ATA_CHR :
+ TRACE("cylinder_high register read, value = 0x%02X\n",
+ device->regs.cylinder_high);
+ return device -> regs.cylinder_high;
+
+ case ATA_CLR :
+ TRACE("cylinder_low register read, value = 0x%02X\n",
+ device->regs.cylinder_low);
+ return device -> regs.cylinder_low;
+
+ case ATA_DR :
+ if (!device->regs.status & ATA_SR_DRQ)
+ {
+ TRACE("data register read, while DRQ bit negated\n" );
+ return 0;
+ }
+ else
+ {
+ TRACE("data register read, value = 0x%04X, cnt = %3d\n",
+ *device->internals.dbuf_ptr, device->internals.dbuf_cnt);
+ if (!--device->internals.dbuf_cnt)
+ device->regs.status &= ~ATA_SR_DRQ;
+ return *device -> internals.dbuf_ptr++;
+ }
+
+ case ATA_DHR :
+ TRACE("device_head register read, value = 0x%02X\n",
+ device->regs.device_head);
+ return device -> regs.device_head;
+
+ case ATA_ERR :
+ TRACE("error register read, value = 0x%02X\n",
+ device->regs.error);
+ return device -> regs.error;
+
+ case ATA_SCR :
+ TRACE("sectorcount register read, value = 0x%02X\n",
+ device->regs.sector_count);
+ return device -> regs.sector_count;
+
+ case ATA_SNR :
+ TRACE("sectornumber register read, value = 0x%02X\n",
+ device->regs.sector_number);
+ return device -> regs.sector_number;
+
+ case ATA_SR :
+ TRACE("status register read\n");
+ if ( (device->regs.device_head & ATA_DHR_DEV) == device->internals.dev)
+ return device -> regs.status;
+ else
+ {
+ TRACE("device0 responds for device1, sr = 0x00\n");
+ return 0; // return 0 when device0 responds for device1
+ }
+
+// case ATA_DA :
+// return device -> regs.status;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ D E V I C E S _ W R I T E
+*/
+/* Write to devices */
+void ata_devices_write(ata_devices *devices, char adr, short value)
+{
+ /* check for no connected devices */
+ if (!devices->device0.stream && !devices->device1.stream)
+ ERR("ata_devices_write, no ata devices connected.\n");
+ else
+ {
+ /* first device */
+ if (devices->device0.stream)
+ ata_device_write(&devices->device0, adr, value);
+
+ /* second device */
+ if (devices->device1.stream)
+ ata_device_write(&devices->device1, adr, value);
+ }
+}
+
+/* write to a single device */
+void ata_device_write(ata_device *device, char adr, short value)
+{
+ switch (adr) {
+ case ATA_CR :
+ /*display debug information */
+ TRACE("command register written, value = 0x%02X\n", value);
+
+ device->regs.command = value;
+
+ /* check command register settings and execute command */
+ ata_device_do_command_register(device);
+ break;
+
+
+ case ATA_CHR :
+ /*display debug information */
+ TRACE("cylinder high register written, value = 0x%02X\n", value);
+
+ device->regs.cylinder_high = value;
+ break;
+
+ case ATA_CLR :
+ /*display debug information */
+ TRACE("cylinder low register written, value = 0x%02X\n", value);
+
+ device->regs.cylinder_low = value;
+ break;
+
+ case ATA_DR :
+ /*display debug information */
+ TRACE("data register written, value = 0x%04X\n", value);
+
+ device->regs.dataport_i = value;
+ break;
+
+ case ATA_DCR :
+ /*display debug information */
+ TRACE("device control register written, value = 0x%02X\n", value);
+
+ device->regs.device_control = value;
+ ata_device_do_control_register(device);
+ break;
+
+ case ATA_DHR :
+ /*display debug information */
+ TRACE("device head register written, value = 0x%02X\n", value);
+
+ device->regs.device_head = value;
+ break;
+
+ case ATA_FR :
+ /*display debug information */
+ TRACE("features register written, value = 0x%02X\n", value);
+
+ device->regs.features = value;
+ break;
+
+ case ATA_SCR :
+ /*display debug information */
+ TRACE("sectorcount register written, value = 0x%02X\n", value);
+
+ device->regs.sector_count = value;
+ break;
+
+ case ATA_SNR :
+ /*display debug information */
+ TRACE("sectornumber register written, value = 0x%02X\n", value);
+
+ device->regs.sector_number = value;
+ break;
+
+ } //endcase
+}
+
Index: fb.c
===================================================================
--- fb.c (nonexistent)
+++ fb.c (revision 1765)
@@ -0,0 +1,395 @@
+/* fb.c -- Simple frame buffer
+ Copyright (C) 2001 Marko Mlinar, markom@opencores.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "sim-config.h"
+#include "abstract.h"
+#include "fb.h"
+#include "sched.h"
+
+#define FB_WRAP (512*1024)
+
+struct fb_state {
+ int enabled;
+ unsigned long pal[256];
+ int ctrl;
+ int pic;
+ int in_refresh;
+ int refresh_count;
+ oraddr_t addr;
+ oraddr_t cam_addr;
+ int camerax;
+ int cameray;
+ int camera_pos;
+ oraddr_t baseaddr;
+ int refresh;
+ int refresh_rate;
+ char *filename;
+};
+
+static void change_buf_addr (struct fb_state *fb, oraddr_t addr)
+{
+ fb->addr = addr;
+}
+
+/* Write a register */
+void fb_write32 (oraddr_t addr, uint32_t value, void *dat)
+{
+ struct fb_state *fb = dat;
+
+ switch (addr) {
+ case FB_CTRL: fb->ctrl = value; break;
+ case FB_BUFADDR: change_buf_addr (fb, value); break;
+ case FB_CAMBUFADDR: fb->cam_addr = value; break;
+ case FB_CAMPOSADDR: fb->camera_pos = value;
+ fb->camerax = value % FB_SIZEX;
+ fb->cameray = value / FB_SIZEX;
+ break;
+ default:
+ addr -= FB_PAL;
+ addr /= 4;
+ if (addr < 0 || addr >= 256) {
+ fprintf (stderr, "Write out of palette buffer (0x%"PRIxADDR")!\n", addr);
+ } else fb->pal[addr] = value;
+ break;
+ }
+}
+
+/* Read a register */
+oraddr_t fb_read32 (oraddr_t addr, void *dat)
+{
+ struct fb_state *fb = dat;
+
+ switch (addr) {
+ case FB_CTRL:
+ return (fb->ctrl & ~0xff000000) | (fb->in_refresh ? 0x80000000 : 0) | ((unsigned long)(fb->refresh_count & 0x7f) << 24);
+ break;
+ case FB_BUFADDR: return fb->addr; break;
+ case FB_CAMBUFADDR: return fb->cam_addr; break;
+ case FB_CAMPOSADDR: return fb->camera_pos; break;
+ default:
+ addr -= FB_PAL;
+ addr /= 4;
+ if (addr < 0 || addr >= 256) {
+ fprintf (stderr, "Read out of palette buffer (0x%"PRIxADDR")!\n", addr);
+ return 0;
+ } else return fb->pal[addr];
+ }
+}
+
+/* define these also for big endian */
+#if __BIG_ENDIAN__
+#define CNV32(x) (\
+ ((((x) >> 24) & 0xff) << 0)\
+ | ((((x) >> 16) & 0xff) << 8)\
+ | ((((x) >> 8) & 0xff) << 16)\
+ | ((((x) >> 0) & 0xff) << 24))
+#define CNV16(x) (\
+ ((((x) >> 8) & 0xff) << 0)\
+ | ((((x) >> 0) & 0xff) << 8))
+#else
+#define CNV16(x) (x)
+#define CNV32(x) (x)
+#endif
+
+/* Dumps a bmp file, based on current image */
+static int fb_dump_image8 (struct fb_state *fb, char *filename)
+{
+ int sx = FB_SIZEX;
+ int sy = FB_SIZEY;
+ int i, x = 0, y = 0;
+ FILE *fo;
+
+ unsigned short int u16;
+ unsigned long int u32;
+
+ if (config.sim.verbose) PRINTF ("Creating %s...", filename);
+ fo = fopen (filename, "wb+");
+ u16 = CNV16(19778); /* BM */
+ if (!fwrite (&u16, 2, 1, fo)) return 1;
+ u32 = CNV32(14 + 40 + sx * sy + 1024); /* size */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(0); /* reserved */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = 14 + 40 + 1024; /* offset */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+
+ u32 = CNV32(40); /* header size */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(sx); /* width */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(sy); /* height */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u16 = CNV16(1); /* planes */
+ if (!fwrite (&u16, 2, 1, fo)) return 1;
+ u16 = CNV16(8); /* bits */
+ if (!fwrite (&u16, 2, 1, fo)) return 1;
+ u32 = CNV32(0); /* compression */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(x * y); /* image size */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(2835); /* x resolution */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(2835); /* y resolution */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(0); /* ncolours = 0; should be generated */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(0); /* important colours; all are important */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+
+ for (i = 0; i < 256; i++) {
+ unsigned long val, d;
+ d = fb->pal[i];
+#if 1
+ val = ((d >> 0) & 0x1f) << 3; /* Blue */
+ val |= ((d >> 5) & 0x3f) << 10; /* Green */
+ val |= ((d >> 11) & 0x1f) << 19; /* Red */
+#else
+ val = CNV32(pal[i]);
+#endif
+ if (!fwrite (&val, 4, 1, fo)) return 1;
+ }
+
+ if (config.sim.verbose) PRINTF ("(%i,%i)", sx, sy);
+ /* Data is stored upside down */
+ for (y = sy - 1; y >= 0; y--) {
+ int align = (4 - sx) % 4;
+ int zero = CNV32(0);
+ int add;
+ while (align < 0) align += 4;
+ for (x = 0; x < sx; x++) {
+ add = (fb->addr & ~(FB_WRAP - 1)) | ((fb->addr + y * sx + x) & (FB_WRAP - 1));
+ fputc (eval_direct8 (add, 0, 0), fo);
+ }
+ if (align && !fwrite (&zero, align, 1, fo)) return 1;
+ }
+
+ if (config.sim.verbose) PRINTF ("DONE\n");
+ fclose (fo);
+ return 0;
+}
+
+/* Dumps a bmp file, based on current image */
+static int fb_dump_image24 (struct fb_state *fb, char *filename)
+{
+ int sx = FB_SIZEX;
+ int sy = FB_SIZEY;
+ int x = 0, y = 0;
+ FILE *fo;
+
+ unsigned short int u16;
+ unsigned long int u32;
+
+ if (config.sim.verbose) PRINTF ("Creating %s...", filename);
+ fo = fopen (filename, "wb+");
+ u16 = CNV16(19778); /* BM */
+ if (!fwrite (&u16, 2, 1, fo)) return 1;
+ u32 = CNV32(14 + 40 + sx * sy * 3); /* size */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(0); /* reserved */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = 14 + 40; /* offset */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+
+ u32 = CNV32(40); /* header size */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(sx); /* width */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(sy); /* height */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u16 = CNV16(1); /* planes */
+ if (!fwrite (&u16, 2, 1, fo)) return 1;
+ u16 = CNV16(24); /* bits */
+ if (!fwrite (&u16, 2, 1, fo)) return 1;
+ u32 = CNV32(0); /* compression */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(x * y * 3); /* image size */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(2835); /* x resolution */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(2835); /* y resolution */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(0); /* ncolours = 0; should be generated */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+ u32 = CNV32(0); /* important colours; all are important */
+ if (!fwrite (&u32, 4, 1, fo)) return 1;
+
+ if (config.sim.verbose) PRINTF ("(%i,%i)", sx, sy);
+ /* Data is stored upside down */
+ for (y = sy - 1; y >= 0; y--) {
+ unsigned char line[FB_SIZEX][3];
+ for (x = 0; x < sx; x++)
+ if (y >= fb->cameray && x >= fb->camerax && y < fb->cameray + CAM_SIZEY && x < fb->camerax + CAM_SIZEX) {
+ int add = (fb->cam_addr + (x - fb->camerax + (y - fb->cameray) * CAM_SIZEX) * 2) ^ 2;
+ unsigned short d = eval_direct16 (add, 0, 0);
+ line[x][0] = ((d >> 0) & 0x1f) << 3; /* Blue */
+ line[x][1] = ((d >> 5) & 0x3f) << 2; /* Green */
+ line[x][2] = ((d >> 11) & 0x1f) << 3; /* Red */
+ } else {
+ int add = (fb->addr & ~(FB_WRAP - 1)) | ((fb->addr + y * sx + x) & (FB_WRAP - 1));
+ unsigned short d = fb->pal[eval_direct8 (add, 0, 0)];
+ line[x][0] = ((d >> 0) & 0x1f) << 3; /* Blue */
+ line[x][1] = ((d >> 5) & 0x3f) << 2; /* Green */
+ line[x][2] = ((d >> 11) & 0x1f) << 3; /* Red */
+ }
+ if(!fwrite (line, sizeof(line), 1, fo)) return 1;
+ }
+
+ if (config.sim.verbose) PRINTF ("DONE\n");
+ fclose (fo);
+ return 0;
+}
+
+void fb_job (void *dat)
+{
+ struct fb_state *fb = dat;
+
+ if (fb->refresh) {
+ /* dump the image? */
+ if (fb->ctrl & 1) {
+ char temp[STR_SIZE];
+ sprintf (temp, "%s%04i.bmp", fb->filename, fb->pic);
+ if (fb->ctrl & 2) fb_dump_image24 (fb, temp);
+ else fb_dump_image8 (fb, temp);
+ fb->pic++;
+ }
+ SCHED_ADD(fb_job, dat, fb->refresh_rate / REFRESH_DIVIDER);
+ fb->in_refresh = 0;
+ fb->refresh = 0;
+ } else {
+ fb->refresh_count++;
+ fb->refresh = 1;
+ SCHED_ADD(fb_job, dat, fb->refresh_rate / REFRESH_DIVIDER);
+ }
+}
+
+/* Reset all FBs */
+void fb_reset (void *dat)
+{
+ struct fb_state *fb = dat;
+ int i;
+
+ fb->pic = 0;
+ fb->addr = 0;
+ fb->ctrl = 0;
+
+ for (i = 0; i < 256; i++)
+ fb->pal[i] = (i << 16) | (i << 8) | (i << 0);
+
+ SCHED_ADD(fb_job, dat, fb->refresh_rate);
+ fb->refresh = 0;
+}
+
+/*-----------------------------------------------------[ FB configuration ]---*/
+void fb_baseaddr(union param_val val, void *dat)
+{
+ struct fb_state *fb = dat;
+ fb->baseaddr = val.addr_val;
+}
+
+void fb_refresh_rate(union param_val val, void *dat)
+{
+ struct fb_state *fb = dat;
+ fb->refresh_rate = val.int_val;
+}
+
+void fb_filename(union param_val val, void *dat)
+{
+ struct fb_state *fb = dat;
+ if(!(fb->filename = strdup(val.str_val))) {
+ fprintf(stderr, "Peripheral FB: Run out of memory\n");
+ exit(-1);
+ }
+}
+
+void fb_enabled(union param_val val, void *dat)
+{
+ struct fb_state *fb = dat;
+ fb->enabled = val.int_val;
+}
+
+void *fb_sec_start(void)
+{
+ struct fb_state *new = malloc(sizeof(struct fb_state));
+
+ if(!new) {
+ fprintf(stderr, "Peripheral FB: Run out of memory\n");
+ exit(-1);
+ }
+
+ new->baseaddr = 0;
+ new->ctrl = 0;
+ new->pic = 0;
+ new->in_refresh = 1;
+ new->refresh_count = 0;
+ new->addr = 0;
+ new->cam_addr = 0;
+ new->camerax = 0;
+ new->cameray = 0;
+ new->camera_pos = 0;
+ new->enabled = 1;
+
+ return new;
+}
+
+void fb_sec_end(void *dat)
+{
+ struct fb_state *fb = dat;
+ struct mem_ops ops;
+
+ if(!fb->enabled) {
+ free(dat);
+ return;
+ }
+
+ memset(&ops, 0, sizeof(struct mem_ops));
+
+ ops.readfunc32 = fb_read32;
+ ops.writefunc32 = fb_write32;
+ ops.write_dat32 = dat;
+ ops.read_dat32 = dat;
+
+ /* FIXME: Correct delay? */
+ ops.delayr = 2;
+ ops.delayw = 2;
+
+ reg_mem_area(fb->baseaddr, FB_PAL + 256*4, 0, &ops);
+
+ reg_sim_reset(fb_reset, dat);
+}
+
+void reg_fb_sec(void)
+{
+ struct config_section *sec = reg_config_sec("fb", fb_sec_start, fb_sec_end);
+
+ reg_config_param(sec, "baseaddr", paramt_addr, fb_baseaddr);
+ reg_config_param(sec, "enabled", paramt_int, fb_enabled);
+ reg_config_param(sec, "refresh_rate", paramt_int, fb_refresh_rate);
+ reg_config_param(sec, "filename", paramt_str, fb_filename);
+}
fb.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: atahost.c
===================================================================
--- atahost.c (nonexistent)
+++ atahost.c (revision 1765)
@@ -0,0 +1,381 @@
+/*
+ atahost.c -- ATA Host code simulation
+ Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+/* get a prototype for 'reg_mem_area()', and 'adjust_rw_delay()' */
+#include "abstract.h"
+#include "sim-config.h"
+#include "sched.h"
+
+/* all user defineable settings are in 'atahost_define.h' */
+#include "atahost_define.h"
+#include "atahost.h"
+
+/* reset and initialize ATA host core(s) */
+void ata_reset(void *dat)
+{
+ ata_host *ata = dat;
+
+ // reset the core registers
+ ata->regs.ctrl = 0x0001;
+ ata->regs.stat = (DEV_ID << 28) | (REV << 24);
+ ata->regs.pctr = (PIO_MODE0_TEOC << ATA_TEOC) | (PIO_MODE0_T4 << ATA_T4) | (PIO_MODE0_T2 << ATA_T2) | (PIO_MODE0_T1 << ATA_T1);
+ ata->regs.pftr0 = (PIO_MODE0_TEOC << ATA_TEOC) | (PIO_MODE0_T4 << ATA_T4) | (PIO_MODE0_T2 << ATA_T2) | (PIO_MODE0_T1 << ATA_T1);
+ ata->regs.pftr1 = (PIO_MODE0_TEOC << ATA_TEOC) | (PIO_MODE0_T4 << ATA_T4) | (PIO_MODE0_T2 << ATA_T2) | (PIO_MODE0_T1 << ATA_T1);
+ ata->regs.dtr0 = (DMA_MODE0_TEOC << ATA_TEOC) | (DMA_MODE0_TD << ATA_TD) | (DMA_MODE0_TM << ATA_TM);
+ ata->regs.dtr1 = (DMA_MODE0_TEOC << ATA_TEOC) | (DMA_MODE0_TD << ATA_TD) | (DMA_MODE0_TM << ATA_TM);
+ ata->regs.txb = 0;
+
+ // inform simulator about new read/write delay timings
+ adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) );
+
+ /* the reset bit in the control register 'ctrl' is set, reset connect ata-devices */
+ ata_devices_hw_reset(&ata->devices, 1);
+}
+/* ========================================================================= */
+
+
+/*
+ Read a register
+*/
+uint32_t ata_read32( oraddr_t addr, void *dat )
+{
+ ata_host *ata = dat;
+
+ /* determine if ata_host or ata_device addressed */
+ if (is_ata_hostadr(addr))
+ {
+ // Accesses to internal register take 2cycles
+ adjust_rw_delay( ata->mem, 2, 2 );
+
+ switch( addr ) {
+ case ATA_CTRL :
+ return ata -> regs.ctrl;
+
+ case ATA_STAT :
+ return ata -> regs.stat;
+
+ case ATA_PCTR :
+ return ata -> regs.pctr;
+
+#if (DEV_ID > 1)
+ case ATA_PFTR0:
+ return ata -> regs.pftr0;
+
+ case ATA_PFTR1:
+ return ata -> regs.pftr1;
+#endif
+
+#if (DEV_ID > 2)
+ case ATA_DTR0 :
+ return ata -> regs.dtr0;
+
+ case ATA_DTR1 :
+ return ata -> regs.dtr1;
+
+ case ATA_RXB :
+ return ata -> regs.rxb;
+#endif
+
+ default:
+ return 0;
+ }
+ }
+ else
+ /* check if the controller is enabled */
+ if (ata->regs.ctrl & ATA_IDE_EN)
+ {
+ // make sure simulator uses correct read/write delay timings
+#if (DEV_ID > 1)
+ if ( (addr & 0x7f) == ATA_DR)
+ {
+ if (ata->devices.dev)
+ adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) );
+ else
+ adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) );
+ }
+ else
+#endif
+ adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) );
+
+ return ata_devices_read(&ata->devices, addr & 0x7f);
+ }
+ return 0;
+}
+/* ========================================================================= */
+
+
+/*
+ Write a register
+*/
+void ata_write32( oraddr_t addr, uint32_t value, void *dat )
+{
+ ata_host *ata = dat;
+
+ /* determine if ata_host or ata_device addressed */
+ if (is_ata_hostadr(addr))
+ {
+ // Accesses to internal register take 2cycles
+ adjust_rw_delay( ata->mem, 2, 2 );
+
+ switch( addr ) {
+ case ATA_CTRL :
+ ata -> regs.ctrl = value;
+
+ /* check if reset bit set, if so reset ata-devices */
+ if (value & ATA_RST)
+ ata_devices_hw_reset(&ata->devices, 1);
+ else
+ ata_devices_hw_reset(&ata->devices, 0);
+ break;
+
+ case ATA_STAT :
+ ata -> regs.stat = (ata -> regs.stat & ~ATA_IDEIS) | (ata -> regs.stat & ATA_IDEIS & value);
+ break;
+
+ case ATA_PCTR :
+ ata -> regs.pctr = value;
+ break;
+
+ case ATA_PFTR0:
+ ata -> regs.pftr0 = value;
+ break;
+
+ case ATA_PFTR1:
+ ata -> regs.pftr1 = value;
+ break;
+
+ case ATA_DTR0 :
+ ata -> regs.dtr0 = value;
+ break;
+
+ case ATA_DTR1 :
+ ata -> regs.dtr1 = value;
+ break;
+
+ case ATA_TXB :
+ ata -> regs.txb = value;
+ break;
+
+ default:
+ /* ERROR-macro currently only supports simple strings. */
+ /*
+ fprintf(stderr, "ERROR : Unknown register for OCIDEC(%1d).\n", DEV_ID );
+
+ Tried to show some useful info here.
+ But when using 'DM'-simulator-command, the screen gets filled with these messages.
+ Thereby eradicating the usefulness of the message
+ */
+ break;
+ }
+ }
+ else
+ /* check if the controller is enabled */
+ if (ata->regs.ctrl & ATA_IDE_EN)
+ {
+ // make sure simulator uses correct read/write delay timings
+#if (DEV_ID > 1)
+ if ( (addr & 0x7f) == ATA_DR)
+ {
+ if (ata->devices.dev)
+ adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) );
+ else
+ adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) );
+ }
+ else
+#endif
+ adjust_rw_delay( ata->mem, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) );
+
+ ata_devices_write(&ata->devices, addr & 0x7f, value);
+ }
+}
+/* ========================================================================= */
+
+
+/* Dump status */
+void ata_status( void *dat )
+{
+ ata_host *ata = dat;
+
+ if ( ata->baseaddr == 0 )
+ return;
+
+ PRINTF( "\nOCIDEC-%1d at: 0x%"PRIxADDR"\n", DEV_ID, ata->baseaddr );
+ PRINTF( "ATA CTRL : 0x%08X\n", ata->regs.ctrl );
+ PRINTF( "ATA STAT : 0x%08x\n", ata->regs.stat );
+ PRINTF( "ATA PCTR : 0x%08x\n", ata->regs.pctr );
+
+#if (DEV_ID > 1)
+ PRINTF( "ATA FCTR0 : 0x%08lx\n", ata->regs.pftr0 );
+ PRINTF( "ATA FCTR1 : 0x%08lx\n", ata->regs.pftr1 );
+#endif
+
+#if (DEV_ID > 2)
+ PRINTF( "ATA DTR0 : 0x%08lx\n", ata->regs.dtr0 );
+ PRINTF( "ATA DTR1 : 0x%08lx\n", ata->regs.dtr1 );
+ PRINTF( "ATA TXD : 0x%08lx\n", ata->regs.txb );
+ PRINTF( "ATA RXD : 0x%08lx\n", ata->regs.rxb );
+#endif
+}
+/* ========================================================================= */
+
+/*----------------------------------------------------[ ATA Configuration ]---*/
+void ata_baseaddr(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ ata->baseaddr = val.addr_val;
+}
+
+void ata_irq(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ ata->irq = val.int_val;
+}
+
+void ata_dev_type0(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ ata->devices.device0.type = val.int_val;
+}
+
+void ata_dev_file0(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ if(!(ata->devices.device0.file = strdup(val.str_val))) {
+ fprintf(stderr, "Peripheral ATA: Run out of memory\n");
+ exit(-1);
+ }
+}
+
+void ata_dev_size0(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ ata->devices.device0.size = val.int_val;
+}
+
+void ata_dev_packet0(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ ata->devices.device0.packet = val.int_val;
+}
+
+void ata_dev_type1(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ ata->devices.device1.packet = val.int_val;
+}
+
+void ata_dev_file1(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ if(!(ata->devices.device1.file = strdup(val.str_val))) {
+ fprintf(stderr, "Peripheral ATA: Run out of memory\n");
+ exit(-1);
+ }
+}
+
+void ata_dev_size1(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ ata->devices.device1.size = val.int_val;
+}
+
+void ata_dev_packet1(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ ata->devices.device1.packet = val.int_val;
+}
+
+void ata_enabled(union param_val val, void *dat)
+{
+ ata_host *ata = dat;
+ ata->enabled = val.int_val;
+}
+
+void *ata_sec_start(void)
+{
+ ata_host *new = malloc(sizeof(ata_host));
+
+ if(!new) {
+ fprintf(stderr, "Peripheral ATA: Run out of memory\n");
+ exit(-1);
+ }
+
+ memset(new, 0, sizeof(ata_host));
+ new->enabled = 1;
+ return new;
+}
+
+void ata_sec_end(void *dat)
+{
+ ata_host *ata = dat;
+ struct mem_ops ops;
+
+ if(!ata->enabled) {
+ free(dat);
+ return;
+ }
+
+ /* Connect ata_devices. */
+ ata_devices_init(&ata->devices);
+
+ memset(&ops, 0, sizeof(struct mem_ops));
+
+ ops.readfunc32 = ata_read32;
+ ops.read_dat32 = dat;
+ ops.writefunc32 = ata_write32;
+ ops.write_dat32 = dat;
+
+ /* Delays will be readjusted later */
+ ops.delayr = 2;
+ ops.delayw = 2;
+
+ ata->mem = reg_mem_area(ata->baseaddr, ATA_ADDR_SPACE, 0, &ops);
+
+ reg_sim_reset(ata_reset, dat);
+ reg_sim_stat(ata_status, dat);
+}
+
+void reg_ata_sec(void)
+{
+ struct config_section *sec = reg_config_sec("ata", ata_sec_start, ata_sec_end);
+
+ reg_config_param(sec, "enabled", paramt_int, ata_enabled);
+ reg_config_param(sec, "baseaddr", paramt_addr, ata_baseaddr);
+ reg_config_param(sec, "irq", paramt_int, ata_irq);
+ reg_config_param(sec, "dev_type0", paramt_int, ata_dev_type0);
+ reg_config_param(sec, "dev_file0", paramt_str, ata_dev_file0);
+ reg_config_param(sec, "dev_size0", paramt_int, ata_dev_size0);
+ reg_config_param(sec, "dev_packet0", paramt_int, ata_dev_packet0);
+ reg_config_param(sec, "dev_type1", paramt_int, ata_dev_type1);
+ reg_config_param(sec, "dev_file1", paramt_str, ata_dev_file1);
+ reg_config_param(sec, "dev_size1", paramt_int, ata_dev_size1);
+ reg_config_param(sec, "dev_packet1", paramt_int, ata_dev_packet1);
+}
Index: vga.c
===================================================================
--- vga.c (nonexistent)
+++ vga.c (revision 1765)
@@ -0,0 +1,316 @@
+/* vga.c -- Definition of types and structures for VGA/LCD
+ Copyright (C) 2001 Marko Mlinar, markom@opencores.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "sim-config.h"
+#include "vga.h"
+#include "abstract.h"
+#include "sched.h"
+
+/* When this counter reaches config.vgas[].refresh_rate, a screenshot is taken and outputted */
+struct vga_state {
+ int enabled;
+ int pics;
+ unsigned long ctrl, stat, htim, vtim;
+ int vbindex;
+ unsigned long vbar[2];
+ unsigned hlen, vlen;
+ int pindex;
+ unsigned long palette[2][256];
+ oraddr_t baseaddr;
+ int refresh_rate;
+ int irq;
+ char *filename;
+};
+
+
+/* Write a register */
+void vga_write32(oraddr_t addr, uint32_t value, void *dat)
+{
+ struct vga_state *vga = dat;
+
+ switch (addr) {
+ case VGA_CTRL: vga->ctrl = value; break;
+ case VGA_STAT: vga->stat = value; break;
+ case VGA_HTIM: vga->htim = value; break;
+ case VGA_VTIM: vga->vtim = value; break;
+ case VGA_HVLEN: vga->hlen = (value >> 16) + 2; vga->hlen = (value & 0xffff) + 2; break;
+ case VGA_VBARA: vga->vbar[0] = value; break;
+ case VGA_VBARB: vga->vbar[1] = value; break;
+ default:
+ if (addr >= VGA_CLUTA && addr < VGA_CLUTB) {
+ vga->palette[0][addr - VGA_CLUTA] = value & 0x00ffffff;
+ } else if (addr >= VGA_CLUTB) {
+ vga->palette[1][addr - VGA_CLUTB] = value & 0x00ffffff;
+ } else {
+ fprintf( stderr, "vga_write32( 0x%"PRIxADDR", 0x%08"PRIx32" ): Out of range\n", addr + vga->baseaddr, value);
+ return;
+ }
+ break;
+ }
+}
+
+/* Read a register */
+uint32_t vga_read32(oraddr_t addr, void *dat)
+{
+ struct vga_state *vga = dat;
+
+ switch (addr) {
+ case VGA_CTRL: return vga->ctrl;
+ case VGA_STAT: return vga->stat;
+ case VGA_HTIM: return vga->htim;
+ case VGA_VTIM: return vga->vtim;
+ case VGA_HVLEN: return ((vga->hlen - 2) << 16) | (vga->vlen - 2);
+ case VGA_VBARA: return vga->vbar[0];
+ case VGA_VBARB: return vga->vbar[1];
+ default:
+ if (addr >= VGA_CLUTA && addr < VGA_CLUTB) {
+ return vga->palette[0][addr - VGA_CLUTA];
+ } else if (addr >= VGA_CLUTB) {
+ return vga->palette[1][addr - VGA_CLUTB];
+ } else {
+ fprintf( stderr, "vga_read32( 0x%"PRIxADDR" ): Out of range\n", addr);
+ return 0;
+ }
+ break;
+ }
+ return 0;
+}
+
+/* This code will only work on little endian machines */
+#ifdef __BIG_ENDIAN__
+#warning Image dump not supported on big endian machines
+
+static int vga_dump_image (char *filename, struct vga_start *vga)
+{
+ return 1;
+}
+
+#else
+
+typedef struct {
+ unsigned short int type; /* Magic identifier */
+ unsigned int size; /* File size in bytes */
+ unsigned short int reserved1, reserved2;
+ unsigned int offset; /* Offset to image data, bytes */
+} BMP_HEADER;
+
+typedef struct {
+ unsigned int size; /* Header size in bytes */
+ int width,height; /* Width and height of image */
+ unsigned short int planes; /* Number of colour planes */
+ unsigned short int bits; /* Bits per pixel */
+ unsigned int compression; /* Compression type */
+ unsigned int imagesize; /* Image size in bytes */
+ int xresolution,yresolution; /* Pixels per meter */
+ unsigned int ncolours; /* Number of colours */
+ unsigned int importantcolours; /* Important colours */
+} INFOHEADER;
+
+
+/* Dumps a bmp file, based on current image */
+static int vga_dump_image (char *filename, struct vga_state *vga)
+{
+ int sx = vga->hlen;
+ int sy = vga->vlen;
+ int i, x = 0, y = 0;
+ int pc = vga->ctrl & VGA_CTRL_PC;
+ int rbpp = vga->ctrl & VGA_CTRL_CD;
+ int bpp = rbpp >> 8;
+
+ BMP_HEADER bh;
+ INFOHEADER ih;
+ FILE *fo;
+
+ if (!sx || !sy) return 1;
+
+ /* 16bpp and 32 bpp will be converted to 24bpp */
+ if (bpp == 1 || bpp == 3) bpp = 2;
+
+ bh.type = 19778; /* BM */
+ bh.size = sizeof (BMP_HEADER) + sizeof (INFOHEADER) + sx * sy * (bpp * 4 + 4) + (pc ? 1024 : 0);
+ bh.reserved1 = bh.reserved2 = 0;
+ bh.offset = sizeof (BMP_HEADER) + sizeof (INFOHEADER) + (pc ? 1024 : 0);
+
+ ih.size = sizeof (INFOHEADER);
+ ih.width = sx; ih.height = sy;
+ ih.planes = 1; ih.bits = bpp * 4 + 4;
+ ih.compression = 0; ih.imagesize = x * y * (bpp * 4 + 4);
+ ih.xresolution = ih.yresolution = 0;
+ ih.ncolours = 0; /* should be generated */
+ ih.importantcolours = 0; /* all are important */
+
+ fo = fopen (filename, "wb+");
+ if (!fwrite (&bh, sizeof (BMP_HEADER), 1, fo)) return 1;
+ if (!fwrite (&ih, sizeof (INFOHEADER), 1, fo)) return 1;
+
+ if (pc) { /* Write palette? */
+ for (i = 0; i < 256; i++) {
+ unsigned long val, d;
+ d = vga->palette[vga->pindex][i];
+ val = (d >> 0) & 0xff; /* Blue */
+ val |= (d >> 8) & 0xff; /* Green */
+ val |= (d >> 16) & 0xff; /* Red */
+ if (!fwrite (&val, sizeof (val), 1, fo)) return 1;
+ }
+ }
+
+ /* Data is stored upside down */
+ for (y = sy - 1; y >= 0; y--) {
+ int align = 4 - ((bpp + 1) * sx) % 4;
+ int zero = 0;
+ for (x = 0; x < sx; x++) {
+ unsigned long pixel = eval_direct32 (vga->vbar[vga->vbindex] + (y * sx + x) * (bpp + 1), 0, 0);
+ if (!fwrite (&pixel, sizeof (pixel), 1, fo)) return 1;
+ }
+ if (!fwrite (&zero, align, 1, fo)) return 1;
+ }
+
+ fclose (fo);
+ return 0;
+}
+#endif /* !__BIG_ENDIAN__ */
+
+void vga_job (void *dat)
+{
+ struct vga_state *vga = dat;
+ /* dump the image? */
+ char temp[STR_SIZE];
+ sprintf (temp, "%s%04i.bmp", vga->filename, vga->pics++);
+ vga_dump_image (temp, vga);
+
+ SCHED_ADD(vga_job, dat, vga->refresh_rate);
+}
+
+/* Reset all VGAs */
+void vga_reset (void *dat)
+{
+ struct vga_state *vga = dat;
+
+ int i;
+
+ /* Init palette */
+ for (i = 0; i < 256; i++)
+ vga->palette[0][i] = vga->palette[1][i] = 0;
+
+ vga->ctrl = vga->stat = vga->htim = vga->vtim = 0;
+ vga->hlen = vga->vlen = 0;
+ vga->vbar[0] = vga->vbar[1] = 0;
+
+ /* Init screen dumping machine */
+ vga->pics = 0;
+
+ vga->pindex = 0;
+ vga->vbindex = 0;
+
+ SCHED_ADD(vga_job, dat, vga->refresh_rate);
+}
+
+/*----------------------------------------------------[ VGA Configuration ]---*/
+void vga_baseaddr(union param_val val, void *dat)
+{
+ struct vga_state *vga = dat;
+ vga->baseaddr = val.addr_val;
+}
+
+void vga_irq(union param_val val, void *dat)
+{
+ struct vga_state *vga = dat;
+ vga->irq = val.int_val;
+}
+
+void vga_refresh_rate(union param_val val, void *dat)
+{
+ struct vga_state *vga = dat;
+ vga->refresh_rate = val.int_val;
+}
+
+void vga_filename(union param_val val, void *dat)
+{
+ struct vga_state *vga = dat;
+ if(!(vga->filename = strdup (val.str_val)));
+}
+
+void vga_enabled(union param_val val, void *dat)
+{
+ struct vga_state *vga = dat;
+ vga->enabled = val.int_val;
+}
+
+void *vga_sec_start(void)
+{
+ struct vga_state *new = malloc(sizeof(struct vga_state));
+
+ if(!new) {
+ fprintf(stderr, "Peripheral VGA: Run out of memory\n");
+ exit(-1);
+ }
+
+ new->baseaddr = 0;
+ new->enabled = 1;
+
+ return new;
+}
+
+void vga_sec_end(void *dat)
+{
+ struct vga_state *vga = dat;
+ struct mem_ops ops;
+
+ if(!vga->enabled) {
+ free(dat);
+ return;
+ }
+
+ memset(&ops, 0, sizeof(struct mem_ops));
+
+ ops.readfunc32 = vga_read32;
+ ops.writefunc32 = vga_write32;
+ ops.write_dat32 = dat;
+ ops.read_dat32 = dat;
+
+ /* FIXME: Correct delay? */
+ ops.delayr = 2;
+ ops.delayw = 2;
+
+ reg_mem_area(vga->baseaddr, VGA_ADDR_SPACE, 0, &ops);
+
+ reg_sim_reset(vga_reset, dat);
+}
+
+void reg_vga_sec(void)
+{
+ struct config_section *sec = reg_config_sec("vga", vga_sec_start, vga_sec_end);
+
+ reg_config_param(sec, "baseaddr", paramt_addr, vga_baseaddr);
+ reg_config_param(sec, "enabled", paramt_int, vga_enabled);
+ reg_config_param(sec, "irq", paramt_int, vga_irq);
+ reg_config_param(sec, "refresh_rate", paramt_int, vga_refresh_rate);
+ reg_config_param(sec, "filename", paramt_str, vga_filename);
+}
vga.c
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: atadevice_cmdi.c
===================================================================
--- atadevice_cmdi.c (nonexistent)
+++ atadevice_cmdi.c (revision 1765)
@@ -0,0 +1,932 @@
+/*
+ atadevice_cmdi.c -- ATA Device simulation
+ Command interpreter for the simulated harddisk.
+ Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ For fun, count the number of FIXMEs :-(
+*/
+
+#include
+
+#include "atadevice.h"
+#include "atadevice_cmdi.h"
+#include "atacmd.h"
+
+#include "debug.h"
+
+DEFAULT_DEBUG_CHANNEL(ata);
+
+int ata_device_execute_cmd(ata_device *device)
+{
+ /*display debug information */
+ TRACE("ata_device_execute_command called with command = 0x%02X\n",
+ device->regs.command);
+
+ /* execute the commands */
+ switch (device->regs.command) {
+
+ case DEVICE_RESET :
+ ata_device_reset_cmd(device);
+ return 0;
+
+ case EXECUTE_DEVICE_DIAGNOSTICS :
+ ata_execute_device_diagnostics_cmd(device);
+ return 0;
+
+ case IDENTIFY_DEVICE :
+ ata_identify_device_cmd(device);
+ return 0;
+
+ case INITIALIZE_DEVICE_PARAMETERS :
+ ata_initialize_device_parameters_cmd(device);
+ return 0;
+
+ case READ_SECTORS :
+ ata_read_sectors_cmd(device);
+
+ default :
+ return -1;
+ }
+}
+
+
+
+/*
+ A T A _ S E T _ D E V I C E _ S I G N A T U R E
+
+ called whenever a command needs to signal the device type (packet, non-packet)
+*/
+void ata_set_device_signature(ata_device *device, int signature)
+{
+ if (signature)
+ {
+ /* place PACKET Command feature set signature in register block */
+ device->regs.sector_count = 0x01;
+ device->regs.sector_number = 0x01;
+ device->regs.cylinder_low = 0x14;
+ device->regs.cylinder_high = 0xEB;
+ }
+ else
+ {
+ /* place NON_PACKET Command feature set signature in register block */
+ device->regs.sector_count = 0x01;
+ device->regs.sector_number = 0x01;
+ device->regs.cylinder_low = 0x00;
+ device->regs.cylinder_high = 0x00;
+ device->regs.device_head = 0x00;
+ }
+}
+
+
+/*
+ A T A _ D E V I C E _ R E S E T
+*/
+void ata_device_reset_cmd(ata_device *device)
+{
+ /* print debug information */
+ TRACE("executing command 'device reset'\n");
+
+ if (!device->packet)
+ WARN("executing DEVICE_RESET on non-packet device.");
+
+ ata_execute_device_diagnostics_cmd(device);
+}
+
+
+/*
+ A T A _ E X E C U T E _ D E V I C E _ D I A G N O S T I C S
+*/
+void ata_execute_device_diagnostics_cmd(ata_device *device)
+{
+ /* print debug information */
+ TRACE("executing command 'execute_device_diagnostics'\n");
+
+ /* clear SRST bit, if set */
+ device->regs.device_control &= ~ATA_DCR_RST;
+
+ /* content of features register is undefined */
+
+ /*
+ set device error register
+ Device0: 0x01 = Device0 passed & Device1 passed/not present
+ Device1: 0x01 = Device1 passed
+ */
+ device->regs.error = 0x01;
+ /* something about DASP- and error_register_bit7 */
+ /* if device1 is not present or if device1 is present and passed */
+ /* diagnostics, than bit7 should be cleared. */
+ /* This means we always clear bit7 */
+
+
+ /* check if device implements packet protocol */
+ if (device->packet)
+ {
+ /* place PACKET command feature set signature in register block */
+ ata_set_device_signature(device, PACKET_SIGNATURE);
+
+ device->regs.status &= 0xf8;
+
+ if (device->regs.command == DEVICE_RESET)
+ device->regs.device_head = device->regs.device_head & ATA_DHR_LBA;
+ else
+ device->regs.device_head = 0x00;
+ }
+ else
+ {
+ /* place NON_PACKET Command feature set signature in register block */
+ ata_set_device_signature(device, !PACKET_SIGNATURE);
+
+ device->regs.status &= 0x82;
+ }
+
+
+ /* we passed diagnostics, so set the PDIAG-line */
+ device->sigs.pdiago = 1;
+}
+
+
+
+/*
+ A T A _ I D E N T I F Y _ D E V I C E
+*/
+void ata_identify_device_cmd(ata_device *device)
+{
+ unsigned char *chksum_buf, chksum;
+ unsigned short *buf;
+ int n;
+ unsigned int tmp;
+
+ /* print debug information */
+ TRACE("ata_device executing command 'identify device'\n");
+
+ /* reset databuffer */
+ device->internals.dbuf_cnt = 256;
+ device->internals.dbuf_ptr = device->internals.dbuf;
+
+ buf = device->internals.dbuf;
+ chksum_buf = (unsigned char *)buf;
+
+ /*
+ if number_of_available_sectors (==device->size / BYTES_PER_SECTOR) < 16,514,064 then
+ support CHS translation where:
+ LBA = ( ((cylinder_number*heads_per_cylinder) +head_number) *sectors_per_track ) +sector_number -1;
+
+ Cylinders : 1-255 (or max.cylinders)
+ Heads : 0-15 (or max.heads )
+ Sectors : 0-65535 (or max.sectors )
+ */
+
+ /*
+ 1) Word 1 shall contain the number of user-addressable logical cylinders in the default CHS
+ translation. If the content of words (61:60) is less than 16,514,064 then the content of word 1
+ shall be greater than or equal to one and less than or equal to 65,535. If the content of words
+ (61:60) is greater than or equal to 16,514,064 then the content of
+ word 1 shall be equal to 16,383.
+ 2) Word 3 shall contain the number of user-addressable logical heads in the default CHS
+ translation. The content of word 3 shall be greater than or equal to one and less than or equal to
+ 16. For compatibility with some BIOSs, the content of word 3 may be equal to 15 if the content of
+ word 1 is greater than 8192.
+ 3) Word 6 shall contain the number of user-addressable logical sectors in the default CHS
+ translation. The content of word 6 shall be greater than or equal to one and less than or equal to
+ 63.
+ 4) [(The content of word 1) * (the content of word 3) * (the content of word 6)] shall be less than or
+ equal to 16,514,064
+ 5) Word 54 shall contain the number of user-addressable logical cylinders in the current CHS
+ translation. The content of word 54 shall be greater than or equal to one and less than or
+ equal to 65,535. After power-on of after a hardware reset the content of word 54 shall be equal to
+ the content of word 1.
+ 6) Word 55 shall contain the number of user-addressable logical heads in the current CHS
+ translation. The content of word 55 shall be greater than or equal to one and less than or equal
+ to 16. After power-on or after a hardware reset the content of word 55 shall equal the content of
+ word 3.
+ 7) Word 56 shall contain the user-addressable logical sectors in the current CHS
+ translation. The content of word 56 should be equal to 63 for compatibility with all BIOSs.
+ However, the content of word 56 may be greater than or equal to one and less than or equal to
+ 255. At power-on or after a hardware reset the content of word 56 shall equal the content of
+ word 6.
+ 8) Words (58:57) shall contain the user-addressable capacity in sectors for the current CHS
+ translation. The content of words (58:57) shall equal [(the content of word 54) * (the content of
+ word 55) * (the content of word 56)] The content of words (58:57) shall be less than or equal to
+ 16,514,064. The content of words (58:57) shall be less than or equal to the content of words
+ (61:60).
+ 9) The content of words 54, 55, 56, and (58:57) may be affected by the host issuing an INITIALIZE
+ DEVICE PARAMETERS command.
+ 10)If the content of words (61:60) is greater than 16,514,064 and if the device does not support CHS
+ addressing, then the content of words 1, 3, 6, 54, 55, 56, and (58:57) shall equal zero. If the
+ content of word 1, word 3, or word 6 equals zero, then the content of words 1, 3, 6, 54, 55, 56,
+ and (58:57) shall equal zero.
+ 11)Words (61:60) shall contain the total number of user-addressable sectors. The content of words
+ (61:60) shall be greater than or equal to one and less than or equal to 268,435,456.
+ 12)The content of words 1, 54, (58:57), and (61:60) may be affected by the host issuing a SET MAX
+ ADDRESS command.
+ */
+
+
+ /* check if this is a NON-PACKET device */
+ if (device->packet)
+ {
+ /*
+ This is a PACKET device.
+ Respond by placing PACKET Command feature set signature in block registers.
+ Abort command.
+ */
+ TRACE("'identify_device' command: This is a PACKET device\n");
+
+ ata_set_device_signature(device, PACKET_SIGNATURE);
+ device->regs.status = ATA_SR_ERR;
+ device->regs.error = ATA_ERR_ABT;
+ }
+ else
+ {
+ /* start filling buffer */
+
+ /*
+ word 0: General configuration
+ 15 : 0 = ATA device
+ 14-8: retired
+ 7 : 1 = removable media device (not set)
+ 6 : 1 = not-removable controller and/or device (set)
+ 5-0 : retired and/or always set to zero
+ */
+ *buf++ = 0x0040;
+
+ /*
+ word 1: Number of logical cylinders
+
+ >=1, <= 65535
+ */
+ if ( (tmp = device->size / BYTES_PER_SECTOR) >= 16514064 )
+ *buf++ = 16383;
+ else
+ if ( (tmp /= (HEADS +1) * SECTORS) > 65535 )
+ *buf++ = 65535;
+ else
+ *buf++ = tmp;
+
+ /*
+ word 2: Specific configuration
+
+ 0x37c8: Device requires SET_FEATURES subcommand to spinup after power-on
+ and IDENTIFY_DEVICE response is incomplete
+ 0x738c: Device requires SET_FEATURES subcommand to spinup after power-on
+ and IDENTIFY_DEVICE response is complete
+ 0x8c73: Device does not require SET_FEATURES subcommand to spinup after power-on
+ and IDENTIFY_DEVICE response is incomplete
+ 0xc837: Device does not require SET_FEATURES subcommand to spinup after power-on
+ and IDENTIFY_DEVICE response is complete
+
+ pick-one
+ */
+ *buf++ = 0xc837;
+
+ /*
+ word 3: Number of logical heads
+
+ >= 1, <= 16
+
+ set to 15 if word1 > 8192 (BIOS compatibility)
+ */
+ *buf++ = HEADS;
+
+ /*
+ word 5-4: retired
+ */
+ buf += 2;
+
+ /*
+ word 6: Number of logical sectors per logical track
+
+ >= 1, <= 63
+ */
+ *buf++ = SECTORS;
+
+ /*
+ word 8-7: Reserved by the CompactFLASH association
+ */
+ buf += 2;
+
+ /*
+ word 9: retired
+ */
+ buf++;
+
+ /*
+ word 19-10: Serial number (ASCII)
+ */
+ /* " www.opencores.org " */
+ *buf++ = (' ' << 8) | 'w';
+ *buf++ = ('w' << 8) | 'w';
+ *buf++ = ('.' << 8) | 'o';
+ *buf++ = ('p' << 8) | 'e';
+ *buf++ = ('n' << 8) | 'c';
+ *buf++ = ('o' << 8) | 'r';
+ *buf++ = ('e' << 8) | 's';
+ *buf++ = ('.' << 8) | 'o';
+ *buf++ = ('r' << 8) | 'g';
+ *buf++ = (' ' << 8) | ' ';
+
+ /*
+ word 22 : obsolete
+ word 21-20: retired
+ */
+ buf += 3;
+
+ /*
+ word 26-23: Firmware revision
+ */
+ strncpy((char *)buf, FIRMWARE, 8);
+ buf += 4;
+
+ /*
+ word 46-27: Model number
+ */
+ /* " ata device model (C)Richard Herveille " */
+ *buf++ = (' ' << 8) | 'a';
+ *buf++ = ('t' << 8) | 'a';
+ *buf++ = (' ' << 8) | 'd';
+ *buf++ = ('e' << 8) | 'v';
+ *buf++ = ('i' << 8) | 'c';
+ *buf++ = ('e' << 8) | ' ';
+ *buf++ = ('m' << 8) | 'o';
+ *buf++ = ('d' << 8) | 'e';
+ *buf++ = ('l' << 8) | ' ';
+ *buf++ = (' ' << 8) | '(';
+ *buf++ = ('C' << 8) | ')';
+ *buf++ = ('R' << 8) | 'i';
+ *buf++ = ('c' << 8) | 'h';
+ *buf++ = ('a' << 8) | 'r';
+ *buf++ = ('d' << 8) | ' ';
+ *buf++ = ('H' << 8) | 'e';
+ *buf++ = ('r' << 8) | 'v';
+ *buf++ = ('e' << 8) | 'i';
+ *buf++ = ('l' << 8) | 'l';
+ *buf++ = ('e' << 8) | ' ';
+
+ /*
+ word 47:
+ 15-8: 0x80
+ 7-0: 0x00 reserved
+ 0x01-0xff maximum number of sectors to be transfered
+ per interrupt on a READ/WRITE MULTIPLE command
+ */
+ *buf++ = 0x8001;
+
+ /*
+ word 48: reserved
+ */
+ buf++;
+
+ /*
+ word 49: Capabilities
+ 15-14: reserved for IDENTIFY PACKET DEVICE
+ 13 : 1=standby timers are supported
+ 0=standby timers are handled by the device FIXME
+ 12 : reserved for IDENTIFY PACKET DEVICE
+ 11 : 1=IORDY supported
+ 0=IORDY may be supported
+ 10 : 1=IORDY may be disabled
+ 9 : set to one
+ 8 : set to one
+ 7-0 : retired
+ */
+ *buf++ = 0x0f00;
+
+ /*
+ word 50: Capabilities
+ 15 : always cleared to zero
+ 14 : always set to one
+ 13-1: reserved
+ 0 : 1=Device specific standby timer minimum value FIXME
+ */
+ *buf++ = 0x4000;
+
+ /*
+ word 52-51: obsolete
+ */
+ buf += 2;
+
+ /*
+ word 53:
+ 15-3: Reserved
+ 2 : 1=value in word 88 is valid
+ 0=value in word 88 is not valid
+ 1 : 1=value in word 64-70 is valid
+ 0=value in word 64-70 is not valid
+ 0 : 1=value in word 54-58 is valid
+ 0=value in word 54-58 is not valid
+ */
+ *buf++ = 0x0007;
+
+
+ /*
+ word 54: number of current logical cylinders (0-65535)
+ */
+ if ( (tmp = device->size / BYTES_PER_SECTOR) > 16514064 )
+ tmp = 16514064;
+
+ tmp /= (device->internals.heads_per_cylinder +1) * (device->internals.sectors_per_track);
+ if (tmp > 65535)
+ *buf++ = 65535;
+ else
+ *buf++ = tmp;
+
+ /*
+ word 55: number of current logical heads, (0-15)
+ */
+ *buf++ = device->internals.heads_per_cylinder +1;
+
+ /*
+ word 56: number of current logical sectors per track (1-255)
+ */
+ *buf++ = device->internals.sectors_per_track;
+
+ /*
+ word 58-57: current capacity in sectors
+ */
+ tmp = *(buf-3) * *(buf-2) * *(buf-1);
+ *buf++ = tmp >> 16;
+ *buf++ = tmp & 0xffff;
+
+ /*
+ word 59:
+ 15-9: reserved
+ 8 : 1=multiple sector setting is valid
+ 7-0 : current setting for number of sectors to be transfered
+ per interrupt on a READ/WRITE MULTIPLE command
+ */
+ *buf++ = 0x0001; // not really a FIXME
+
+ /*
+ word 60-61: Total number of user addressable sectors (LBA only)
+ */
+ *buf++ = (device->size / BYTES_PER_SECTOR);
+ *buf++ = (device->size / BYTES_PER_SECTOR) >> 16;
+
+ /*
+ word 62: obsolete
+ */
+ buf++;
+
+ /* FIXME
+ word 63: DMA settings
+ 15-11: Reserved
+ 10 : 1=Multiword DMA Mode 2 is selected
+ 0=Multiword DMA Mode 2 is not selected
+ 9 : 1=Multiword DMA Mode 1 is selected
+ 0=Multiword DMA Mode 1 is not selected
+ 8 : 1=Multiword DMA Mode 0 is selected
+ 0=Multiword DMA Mode 0 is not selected
+ 7-3 : Reserved
+ 2 : Multiword DMA Mode 2 and below are supported
+ 1 : Multiword DMA Mode 1 and below are supported
+ 0 : Multiword DMA Mode 0 is supported
+ */
+ #if (MWDMA == -1)
+ *buf++ = 0x0000;
+ #elif (MWDMA == 2)
+ *buf++ = 0x0007;
+ #elif (MWDMA == 1)
+ *buf++ = 0x0003;
+ #else
+ *buf++ = 0x0001;
+ #endif
+
+ /*
+ word 64:
+ 15-8: reserved
+ 7-0: Advanced PIO modes supported
+
+ 7-2: reserved
+ 1 : PIO mode4 supported
+ 0 : PIO mode3 supported
+ */
+ *buf++ = 0x0003;
+
+ /*
+ word 65: Minimum Multiword DMA transfer cycle time per word (nsec)
+ */
+ *buf++ = MIN_MWDMA_CYCLE_TIME;
+
+ /*
+ word 66: Manufacturer's recommended Multiword DMA transfer cycle time per word (nsec)
+ */
+ *buf++ = RECOMMENDED_MWDMA_CYCLE_TIME;
+
+
+ /*
+ word 67: Minimum PIO transfer cycle time per word (nsec), without IORDY flow control
+ */
+ *buf++ = MIN_PIO_CYCLE_TIME_NO_IORDY;
+
+ /*
+ word 68: Minimum PIO transfer cycle time per word (nsec), with IORDY flow control
+ */
+ *buf++ = MIN_PIO_CYCLE_TIME_IORDY;
+
+ /*
+ word 69-70: reserved for future command overlap and queueing
+ 71-74: reserved for IDENTIFY PACKET DEVICE command
+ */
+ buf += 6;
+
+ /*
+ word 75: Queue depth
+ 15-5: reserved
+ 4-0: queue depth -1
+ */
+ *buf++ = SUPPORT_READ_WRITE_DMA_QUEUED ? QUEUE_DEPTH : 0x0000;
+
+ /*
+ word 76-79: reserved
+ */
+ buf += 4;
+
+ /*
+ word 80: MAJOR ATA version
+ We simply report that we do not report a version
+
+ You can also set bits 5-2 to indicate compliancy to
+ ATA revisions 5-2 (1 & 0 are obsolete)
+ */
+ *buf++ = 0x0000;
+
+ /*
+ word 81: MINOR ATA version
+ We report ATA/ATAPI-5 T13 1321D revision 3 (0x13)
+ */
+ *buf++ = 0x0013;
+
+ /*
+ word 82: Command set supported
+ */
+ *buf++ = 0 << 15 | /* obsolete */
+ SUPPORT_NOP_CMD << 14 |
+ SUPPORT_READ_BUFFER_CMD << 13 |
+ SUPPORT_WRITE_BUFFER_CMD << 12 |
+ 0 << 11 | /* obsolete */
+ SUPPORT_HOST_PROTECTED_AREA << 10 |
+ SUPPORT_DEVICE_RESET_CMD << 9 |
+ SUPPORT_SERVICE_INTERRUPT << 8 |
+ SUPPORT_RELEASE_INTERRUPT << 7 |
+ SUPPORT_LOOKAHEAD << 6 |
+ SUPPORT_WRITE_CACHE << 5 |
+ 0 << 4 | /* cleared to zero */
+ SUPPORT_POWER_MANAGEMENT << 3 |
+ SUPPORT_REMOVABLE_MEDIA << 2 |
+ SUPPORT_SECURITY_MODE << 1 |
+ SUPPORT_SMART << 0
+ ;
+
+ /*
+ word 83: Command set supported
+ */
+ *buf++ = 0 << 15 | /* cleared to zero */
+ 1 << 14 | /* set to one */
+ 0 << 9 | /* reserved */
+ SUPPORT_SET_MAX << 8 |
+ 0 << 7 | /* reserved for */
+ /* project 1407DT */
+ SET_FEATURES_REQUIRED_AFTER_POWER_UP << 6 |
+ SUPPORT_POWER_UP_IN_STANDBY_MODE << 5 |
+ SUPPORT_REMOVABLE_MEDIA_NOTIFICATION << 4 |
+ SUPPORT_APM << 3 |
+ SUPPORT_CFA << 2 |
+ SUPPORT_READ_WRITE_DMA_QUEUED << 1 |
+ SUPPORT_DOWNLOAD_MICROCODE << 0
+ ;
+
+ /*
+ word 84: Command set/feature supported
+ */
+ *buf++ = 0 << 15 | /* cleared to zero */
+ 1 << 14 /* set to one */
+ ; /* 0-13 reserved */
+
+ /*
+ word 85: Command set enabled FIXME
+ */
+ *buf++ = 0 << 15 | /* obsolete */
+ SUPPORT_NOP_CMD << 14 |
+ SUPPORT_READ_BUFFER_CMD << 13 |
+ SUPPORT_WRITE_BUFFER_CMD << 12 |
+ 0 << 11 | /* obsolete */
+ SUPPORT_HOST_PROTECTED_AREA << 10 |
+ SUPPORT_DEVICE_RESET_CMD << 9 |
+ SUPPORT_SERVICE_INTERRUPT << 8 |
+ SUPPORT_RELEASE_INTERRUPT << 7 |
+ SUPPORT_LOOKAHEAD << 6 |
+ SUPPORT_WRITE_CACHE << 5 |
+ 0 << 4 | /* cleared to zero */
+ SUPPORT_POWER_MANAGEMENT << 3 |
+ SUPPORT_REMOVABLE_MEDIA << 2 |
+ SUPPORT_SECURITY_MODE << 1 |
+ SUPPORT_SMART << 0
+ ;
+
+ /*
+ word 86: Command set enables
+ */
+ *buf++ = 0 << 9 | /* 15-9 reserved */
+ SUPPORT_SET_MAX << 8 |
+ 0 << 7 | /* reserved for */
+ /* project 1407DT */
+ SET_FEATURES_REQUIRED_AFTER_POWER_UP << 6 |
+ SUPPORT_POWER_UP_IN_STANDBY_MODE << 5 |
+ SUPPORT_REMOVABLE_MEDIA_NOTIFICATION << 4 |
+ SUPPORT_APM << 3 |
+ SUPPORT_CFA << 2 |
+ SUPPORT_READ_WRITE_DMA_QUEUED << 1 |
+ SUPPORT_DOWNLOAD_MICROCODE << 0
+ ;
+
+ /*
+ word 87: Command set/feature supported
+ */
+ *buf++ = 0 << 15 | /* cleared to zero */
+ 1 << 14 /* set to one */
+ ; /* 0-13 reserved */
+
+ /*
+ word 88: UltraDMA section
+ 15-13: reserved
+ 12 : 1=UltraDMA Mode 4 is selected
+ 0=UltraDMA Mode 4 is not selected
+ 10 : 1=UltraDMA Mode 3 is selected
+ 0=UltraDMA Mode 3 is not selected
+ 10 : 1=UltraDMA Mode 2 is selected
+ 0=UltraDMA Mode 2 is not selected
+ 9 : 1=UltraDMA Mode 1 is selected
+ 0=UltraDMA Mode 1 is not selected
+ 8 : 1=UltraDMA Mode 0 is selected
+ 0=UltraDMA Mode 0 is not selected
+ 7-5 : Reserved
+ 4 : UltraDMA Mode 4 and below are supported
+ 3 : UltraDMA Mode 3 and below are supported
+ 2 : UltraDMA Mode 2 and below are supported
+ 1 : UltraDMA Mode 1 and below are supported
+ 0 : UltraDMA Mode 0 is supported
+
+ Because the OCIDEC cores currently do not support
+ UltraDMA we set all bits to zero
+ */
+ *buf++ = 0;
+
+ /*
+ word 89: Security sector erase unit completion time
+
+ For now we report a 'value not specified'.
+ */
+ *buf++ = 0x0000; // not really a FIXME
+
+ /*
+ word 90: Enhanced security erase completion time
+
+ For now we report a 'value not specified'.
+ */
+ *buf++ = 0x0000; // not really a FIXME
+
+ /*
+ word 91: Current advanced power management value
+
+ For now set it to zero.
+ */
+ *buf++ = 0x0000; // FIXME
+
+ /*
+ word 92: Master Password Revision Code.
+ We simply report that we do not support this.
+ */
+ *buf++ = 0x0000;
+
+ /*
+ word 93: Hardware reset result
+ */
+ if (device->internals.dev)
+ {
+ /* this is device1, clear device0 bits */
+ *buf++ = 0 << 15 |
+ 1 << 14 |
+ 0 << 13 | /* CBLIBD level (1=Vih, 0=Vil) */
+ /* 12-8 Device 1 hardware reset result */
+ 0 << 12 | /* reserved */
+ device->sigs.pdiago << 11 | /* 1: Device1 did assert PDIAG */
+ /* 0: Device1 did not assert PDIAG */
+ 3 << 9 | /* Device1 determined device number by */
+ /* 00: reserved */
+ /* 01: a jumper was used */
+ /* 10: the CSEL signal was used */
+ /* 11: some other or unknown method was used */
+ 1 << 8 /* set to one */
+ ;
+ }
+ else
+ { /* FIXME bit 6 */
+ /* this is device0, clear device1 bits */
+ *buf++ = 0 << 7 | /* reserved */
+ 0 << 6 | /* 1: Device0 responds for device 1 */
+ /* 0: Device0 does not respond for device1 */
+ device->sigs.daspi << 5 | /* 1: Device0 did detected DASP assertion */
+ /* 0: Device0 did not detect DASP assertion */
+ device->sigs.pdiagi << 4 | /* Device0 did detect PDIAG assertion */
+ /* Device0 did not detect PDIAG assertion */
+ 1 << 3 | /* Device0 did pass diagnostics */
+ 3 << 1 | /* Device0 determined device number by */
+ /* 00: reserved */
+ /* 01: a jumper was used */
+ /* 10: the CSEL signal was used */
+ /* 11: some other or unknown method was used */
+ 1 << 0 /* set to one */
+ ;
+ }
+
+ /*
+ word 94-126: Reserved
+ */
+ buf += 33;
+
+ /*
+ word 127: Removable Media Status Notification feature set support
+ 15-2: reserved
+ 1-0: 00 Removable media Status Notification not supported
+ 01 Removable media Status Notification supported
+ 10 reserved
+ 11 reserved
+ */
+ *buf++ = SUPPORT_REMOVABLE_MEDIA_NOTIFICATION;
+
+ /*
+ word 128: Security status
+ 15-9: reserved
+ 8 : Security level, 0=high, 1=maximum
+ 7-6 : reserved
+ 5 : 1=enhanced security erase supported
+ 4 : 1=security count expired
+ 3 : 1=security frozen
+ 2 : 1=security locked
+ 1 : 1=security enabled
+ 0 : security supported
+
+ for now we do not support security, set is to zero
+ */
+ *buf++ = 0;
+
+ /*
+ word 129-159: Vendor specific
+ */
+ buf += 31;
+
+ /*
+ word 160: CFA power mode 1
+ 15 : Word 160 supported
+ 14 : reserved
+ 13 : CFA power mode 1 is required for one or more commands
+ 12 : CFA power mode 1 disabled
+ 11-0: Maximum current in mA
+ */
+ *buf++ = 0;
+
+ /*
+ word 161-175: Reserved for the CompactFLASH Association
+ */
+ buf += 15;
+
+ /*
+ word 176-254: reserved
+ */
+ buf += 79;
+
+ /*
+ word 255: Integrity word
+ 15-8: Checksum
+ 7-0 : Signature
+ */
+ // set signature to indicate valid checksum
+ *buf = 0x00a5;
+
+ // calculate checksum
+ chksum = 0;
+ for (n=0; n < 511; n++)
+ chksum += *chksum_buf++;
+
+ *buf = ( (0-chksum) << 8) | 0x00a5;
+
+ /* set status register bits */
+ device->regs.status = ATA_SR_DRDY | ATA_SR_DRQ;
+ }
+}
+
+
+/*
+ A T A _ I N I T I A L I Z E _ D E V I C E _ P A R A M E T E R S
+*/
+void ata_initialize_device_parameters_cmd(ata_device *device)
+{
+ /* print debug information */
+ TRACE("executing command 'initialize device parameters'\n");
+
+ device->internals.sectors_per_track = device->regs.sector_count;
+ device->internals.heads_per_cylinder = device->regs.device_head & ATA_DHR_H;
+
+ /* set status register bits */
+ device->regs.status = 0;
+}
+
+
+/*
+ A T A _ R E A D _ S E C T O R S
+*/
+void ata_read_sectors_cmd(ata_device *device)
+{
+ size_t sector_count;
+ unsigned long lba;
+
+ /* print debug information */
+ TRACE("executing command 'read sectors'\n");
+
+ /* check if this is a NON-PACKET device */
+ if (device->packet)
+ {
+ /*
+ This is a PACKET device.
+ Respond by placing PACKET Command feature set signature in block registers.
+ Abort command.
+ */
+ TRACE("'identify_device' command: This is a PACKET device\n");
+
+ ata_set_device_signature(device, PACKET_SIGNATURE);
+ device->regs.status = ATA_SR_ERR;
+ device->regs.error = ATA_ERR_ABT;
+ }
+ else
+ {
+ /* get the sector count */
+ if (device->regs.sector_count == 0)
+ sector_count = 256;
+ else
+ sector_count = device->regs.sector_count;
+
+ /* check if we are using CHS or LBA translation, fill in the bits */
+ if (device->regs.device_head & ATA_DHR_LBA)
+ { /* we are using LBA translation */
+ lba = (device->regs.device_head & ATA_DHR_H) << 24 |
+ (device->regs.cylinder_high ) << 16 |
+ (device->regs.cylinder_low ) << 8 |
+ device->regs.sector_number
+ ;
+ }
+ else
+ { /* we are using CHS translation, calculate lba address */
+ lba = (device->regs.cylinder_high << 16) | device->regs.cylinder_low;
+ lba *= device->internals.heads_per_cylinder;
+ lba += device->regs.device_head & ATA_DHR_H;
+ lba *= device->internals.sectors_per_track;
+ lba += device->regs.sector_number;
+ lba -= 1;
+ }
+
+ /* check if sector within bounds */
+ if (lba > (device->size / BYTES_PER_SECTOR) )
+ { /* invalid sector address */
+ /* set the status & error registers */
+ device->regs.status = ATA_SR_DRDY | ATA_SR_ERR;
+ device->regs.error = ATA_ERR_IDNF;
+ }
+ else
+ { /* go ahead, read the bytestream */
+ lba *= BYTES_PER_SECTOR;
+
+ /* set the file-positon pointer to the start of the sector */
+ fseek(device->stream, lba, SEEK_SET);
+
+ /* get the bytes from the stream */
+ fread(device->internals.dbuf, BYTES_PER_SECTOR, sector_count, device->stream);
+
+ /* set status register bits */
+ device->regs.status = ATA_SR_DRDY | ATA_SR_DRQ;
+
+ /* reset the databuffer */
+ device->internals.dbuf_cnt = sector_count * BYTES_PER_SECTOR /2; //Words, not bytes
+ device->internals.dbuf_ptr = device->internals.dbuf;
+ }
+ }
+}
+
+
Index: 16450.h
===================================================================
--- 16450.h (nonexistent)
+++ 16450.h (revision 1765)
@@ -0,0 +1,213 @@
+/* 16450.h -- Definition of types and structures for 8250/16450 serial UART
+ Copyright (C) 2000 Damjan Lampret, lampret@opencores.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/* Prototypes */
+void uart_reset();
+void uart_status();
+
+/* Definitions */
+#define UART_ADDR_SPACE (8) /* UART memory address space size in bytes */
+#define UART_MAX_FIFO_LEN (16) /* rx FIFO for uart 16550 */
+#define MAX_SKEW (1) /* max. clock skew in subclocks */
+#define UART_VAPI_BUF_LEN 128 /* Size of VAPI command buffer - VAPI should not send more
+ that this amout of char before requesting something back */
+#define UART_CLOCK_DIVIDER 16 /* Uart clock divider */
+#define UART_FGETC_SLOWDOWN 100 /* fgetc slowdown factor */
+
+/* Registers */
+
+struct dev_16450 {
+ struct {
+ uint8_t txbuf[UART_MAX_FIFO_LEN];
+ uint16_t rxbuf[UART_MAX_FIFO_LEN]; /* Upper 8-bits is the LCR modifier */
+ uint8_t dll;
+ uint8_t dlh;
+ uint8_t ier;
+ uint8_t iir;
+ uint8_t fcr;
+ uint8_t lcr;
+ uint8_t mcr;
+ uint8_t lsr;
+ uint8_t msr;
+ uint8_t scr;
+ } regs; /* Visible registers */
+ struct {
+ uint8_t txser; /* Character just sending */
+ uint16_t rxser; /* Character just receiving */
+ uint8_t loopback;
+ } iregs; /* Internal registers */
+ struct {
+ int txbuf_head;
+ int txbuf_tail;
+ int rxbuf_head;
+ int rxbuf_tail;
+ unsigned int txbuf_full;
+ unsigned int rxbuf_full;
+ int receiveing; /* Receiveing a char */
+ int recv_break; /* Receiveing a break */
+ int ints; /* Which interrupts are pending */
+ } istat; /* Internal status */
+
+ /* Clocks per char */
+ unsigned long char_clks;
+
+ /* VAPI internal registers */
+ struct {
+ unsigned long char_clks;
+ uint8_t dll, dlh;
+ uint8_t lcr;
+ int skew;
+ } vapi;
+
+ /* Required by VAPI - circular buffer */
+ unsigned long vapi_buf[UART_VAPI_BUF_LEN]; /* Buffer to store incoming characters to,
+ since we cannot handle them so fast - we
+ are serial */
+ int vapi_buf_head_ptr; /* Where we write to */
+ int vapi_buf_tail_ptr; /* Where we read from */
+
+ /* Length of FIFO, 16 for 16550, 1 for 16450 */
+ int fifo_len;
+
+ struct channel *channel;
+
+ /* Configuration */
+ int enabled;
+ int jitter;
+ oraddr_t baseaddr;
+ int irq;
+ unsigned long vapi_id;
+ int uart16550;
+ char *channel_str;
+};
+
+/*
+ * Addresses of visible registers
+ *
+ */
+#define UART_RXBUF 0 /* R: Rx buffer, DLAB=0 */
+#define UART_TXBUF 0 /* W: Tx buffer, DLAB=0 */
+#define UART_DLL 0 /* R/W: Divisor Latch Low, DLAB=1 */
+#define UART_DLH 1 /* R/W: Divisor Latch High, DLAB=1 */
+#define UART_IER 1 /* R/W: Interrupt Enable Register */
+#define UART_IIR 2 /* R: Interrupt ID Register */
+#define UART_FCR 2 /* W: FIFO Control Register */
+#define UART_LCR 3 /* R/W: Line Control Register */
+#define UART_MCR 4 /* W: Modem Control Register */
+#define UART_LSR 5 /* R: Line Status Register */
+#define UART_MSR 6 /* R: Modem Status Register */
+#define UART_SCR 7 /* R/W: Scratch Register */
+
+/*
+ * R/W masks for valid bits in 8250/16450 (mask out 16550 and later bits)
+ *
+ */
+#define UART_VALID_LCR 0xff
+#define UART_VALID_LSR 0xff
+#define UART_VALID_IIR 0x0f
+#define UART_VALID_FCR 0xc0
+#define UART_VALID_IER 0x0f
+#define UART_VALID_MCR 0x1f
+#define UART_VALID_MSR 0xff
+
+/*
+ * Bit definitions for the Line Control Register
+ *
+ */
+#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
+#define UART_LCR_SBC 0x40 /* Set break control */
+#define UART_LCR_SPAR 0x20 /* Stick parity (?) */
+#define UART_LCR_EPAR 0x10 /* Even parity select */
+#define UART_LCR_PARITY 0x08 /* Parity Enable */
+#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */
+#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */
+#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */
+#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */
+#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */
+#define UART_LCR_RESET 0x03
+/*
+ * Bit definitions for the Line Status Register
+ */
+#define UART_LSR_RXERR 0x80 /* Error in rx fifo */
+#define UART_LSR_TXSERE 0x40 /* Transmitter serial register empty */
+#define UART_LSR_TXBUFE 0x20 /* Transmitter buffer register empty */
+#define UART_LSR_BREAK 0x10 /* Break interrupt indicator */
+#define UART_LSR_FRAME 0x08 /* Frame error indicator */
+#define UART_LSR_PARITY 0x04 /* Parity error indicator */
+#define UART_LSR_OVRRUN 0x02 /* Overrun error indicator */
+#define UART_LSR_RDRDY 0x01 /* Receiver data ready */
+
+/*
+ * Bit definitions for the Interrupt Identification Register
+ */
+#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
+#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
+
+#define UART_IIR_MSI 0x00 /* Modem status interrupt (Low priority) */
+#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
+#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
+#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt (High p.) */
+#define UART_IIR_CTI 0x0c /* Character timeout */
+
+/*
+ * Bit Definitions for the FIFO Control Register
+ */
+#define UART_FCR_FIE 0x01 /* FIFO enable */
+#define UART_FCR_RRXFI 0x02 /* Reset rx FIFO */
+#define UART_FCR_RTXFI 0x04 /* Reset tx FIFO */
+#define UART_FIFO_TRIGGER(x) /* Trigger values for indexes 0..3 */\
+ ((x) == 0 ? 1\
+ :(x) == 1 ? 4\
+ :(x) == 2 ? 8\
+ :(x) == 3 ? 14 : 0)
+
+/*
+ * Bit definitions for the Interrupt Enable Register
+ */
+#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
+#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
+#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
+#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
+
+/*
+ * Bit definitions for the Modem Control Register
+ */
+#define UART_MCR_LOOP 0x10 /* Enable loopback mode */
+#define UART_MCR_AUX2 0x08 /* Auxilary 2 */
+#define UART_MCR_AUX1 0x04 /* Auxilary 1 */
+#define UART_MCR_RTS 0x02 /* Force RTS */
+#define UART_MCR_DTR 0x01 /* Force DTR */
+
+/*
+ * Bit definitions for the Modem Status Register
+ */
+#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
+#define UART_MSR_RI 0x40 /* Ring Indicator */
+#define UART_MSR_DSR 0x20 /* Data Set Ready */
+#define UART_MSR_CTS 0x10 /* Clear to Send */
+#define UART_MSR_DDCD 0x08 /* Delta DCD */
+#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
+#define UART_MSR_DDSR 0x02 /* Delta DSR */
+#define UART_MSR_DCTS 0x01 /* Delta CTS */
+
+/*
+ * Various definitions
+ */
+#define UART_BREAK_COUNT (1) /* # of chars to count when performing break */
+#define UART_CHAR_TIMEOUT (4) /* # of chars to count when performing timeout int. */
Index: dma.c
===================================================================
--- dma.c (nonexistent)
+++ dma.c (revision 1765)
@@ -0,0 +1,543 @@
+/* dma.c -- Simulation of DMA
+ Copyright (C) 2001 by Erez Volk, erez@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ * This simulation of the DMA core is not meant to be full.
+ * It is written only to allow simulating the Ethernet core.
+ * Of course, if anyone feels like perfecting it, feel free...
+ */
+
+#include
+
+#include "config.h"
+
+#ifdef HAVE_INTTYPES_H
+#include
+#endif
+
+#include "port.h"
+#include "arch.h"
+#include "dma.h"
+#include "sim-config.h"
+#include "pic.h"
+#include "abstract.h"
+#include "fields.h"
+#include "sched.h"
+#include "debug.h"
+
+DEFAULT_DEBUG_CHANNEL(dma);
+
+/* We keep a copy of all our controllers because we have to export an interface
+ * to other peripherals eg. ethernet */
+static struct dma_controller *dmas = NULL;
+
+static uint32_t dma_read32( oraddr_t addr, void *dat );
+static void dma_write32( oraddr_t addr, uint32_t value, void *dat );
+
+static unsigned long dma_read_ch_csr( struct dma_channel *channel );
+static void dma_write_ch_csr( struct dma_channel *channel, unsigned long value );
+void dma_controller_clock( struct dma_controller *dma );
+static void dma_load_descriptor( struct dma_channel *channel );
+static void dma_init_transfer( struct dma_channel *channel );
+static void dma_channel_terminate_transfer( struct dma_channel *channel, int generate_interrupt );
+
+void dma_channel_clock( void *dat );
+
+static void masked_increase( oraddr_t *value, unsigned long mask );
+
+#define CHANNEL_ND_I(ch) (TEST_FLAG(ch->regs.csr,DMA_CH_CSR,MODE) && TEST_FLAG(ch->regs.csr,DMA_CH_CSR,USE_ED) && ch->dma_nd_i)
+
+
+/* Reset. Initializes all registers to default and places devices in memory address space. */
+void dma_reset(void *dat)
+{
+ struct dma_controller *dma = dat;
+ unsigned channel_number;
+
+ memset( dma->ch, 0, sizeof(dma->ch) );
+
+ dma->regs.csr = 0;
+ dma->regs.int_msk_a = 0;
+ dma->regs.int_msk_b = 0;
+ dma->regs.int_src_a = 0;
+ dma->regs.int_src_b = 0;
+
+ for ( channel_number = 0; channel_number < DMA_NUM_CHANNELS; ++ channel_number ) {
+ dma->ch[channel_number].controller = dma;
+ dma->ch[channel_number].channel_number = channel_number;
+ dma->ch[channel_number].channel_mask = 1LU << channel_number;
+ dma->ch[channel_number].regs.am0 = dma->ch[channel_number].regs.am1 = 0xFFFFFFFC;
+ }
+}
+
+/* Print register values on stdout */
+void dma_status( void *dat )
+{
+ unsigned j;
+ struct dma_controller *dma = dat;
+
+ if ( dma->baseaddr == 0 )
+ return;
+
+ PRINTF( "\nDMA controller at 0x%"PRIxADDR":\n", dma->baseaddr );
+ PRINTF( "CSR : 0x%08lX\n", dma->regs.csr );
+ PRINTF( "INT_MSK_A : 0x%08lX\n", dma->regs.int_msk_a );
+ PRINTF( "INT_MSK_B : 0x%08lX\n", dma->regs.int_msk_b );
+ PRINTF( "INT_SRC_A : 0x%08lX\n", dma->regs.int_src_a );
+ PRINTF( "INT_SRC_B : 0x%08lX\n", dma->regs.int_src_b );
+
+ for ( j = 0; j < DMA_NUM_CHANNELS; ++ j ) {
+ struct dma_channel *channel = &(dma->ch[j]);
+ if ( !channel->referenced )
+ continue;
+ PRINTF( "CH%u_CSR : 0x%08lX\n", j, channel->regs.csr );
+ PRINTF( "CH%u_SZ : 0x%08lX\n", j, channel->regs.sz );
+ PRINTF( "CH%u_A0 : 0x%08lX\n", j, channel->regs.a0 );
+ PRINTF( "CH%u_AM0 : 0x%08lX\n", j, channel->regs.am0 );
+ PRINTF( "CH%u_A1 : 0x%08lX\n", j, channel->regs.a1 );
+ PRINTF( "CH%u_AM1 : 0x%08lX\n", j, channel->regs.am1 );
+ PRINTF( "CH%u_DESC : 0x%08lX\n", j, channel->regs.desc );
+ PRINTF( "CH%u_SWPTR : 0x%08lX\n", j, channel->regs.swptr );
+ }
+}
+
+
+/* Read a register */
+uint32_t dma_read32( oraddr_t addr, void *dat )
+{
+ struct dma_controller *dma = dat;
+
+ if ( addr < DMA_CH_BASE ) {
+ /* case of global (not per-channel) registers */
+ switch( addr ) {
+ case DMA_CSR: return dma->regs.csr;
+ case DMA_INT_MSK_A: return dma->regs.int_msk_a;
+ case DMA_INT_MSK_B: return dma->regs.int_msk_b;
+ case DMA_INT_SRC_A: return dma->regs.int_src_a;
+ case DMA_INT_SRC_B: return dma->regs.int_src_b;
+ default:
+ fprintf( stderr, "dma_read32( 0x%"PRIxADDR" ): Illegal register\n",
+ addr + dma->baseaddr );
+ return 0;
+ }
+ } else {
+ /* case of per-channel registers */
+ unsigned chno = (addr - DMA_CH_BASE) / DMA_CH_SIZE;
+ addr = (addr - DMA_CH_BASE) % DMA_CH_SIZE;
+ switch( addr ) {
+ case DMA_CH_CSR: return dma_read_ch_csr( &(dma->ch[chno]) );
+ case DMA_CH_SZ: return dma->ch[chno].regs.sz;
+ case DMA_CH_A0: return dma->ch[chno].regs.a0;
+ case DMA_CH_AM0: return dma->ch[chno].regs.am0;
+ case DMA_CH_A1: return dma->ch[chno].regs.a1;
+ case DMA_CH_AM1: return dma->ch[chno].regs.am1;
+ case DMA_CH_DESC: return dma->ch[chno].regs.desc;
+ case DMA_CH_SWPTR: return dma->ch[chno].regs.swptr;
+ }
+ }
+ return 0;
+}
+
+
+/* Handle read from a channel CSR */
+unsigned long dma_read_ch_csr( struct dma_channel *channel )
+{
+ unsigned long result = channel->regs.csr;
+
+ /* before returning, clear all relevant bits */
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, INT_CHUNK_DONE );
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, INT_DONE );
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, INT_ERR );
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
+
+ return result;
+}
+
+
+
+/* Write a register */
+void dma_write32( oraddr_t addr, uint32_t value, void *dat )
+{
+ struct dma_controller *dma = dat;
+
+ /* case of global (not per-channel) registers */
+ if ( addr < DMA_CH_BASE ) {
+ switch( addr ) {
+ case DMA_CSR:
+ if ( TEST_FLAG( value, DMA_CSR, PAUSE ) )
+ fprintf( stderr, "dma: PAUSE not implemented\n" );
+ break;
+
+ case DMA_INT_MSK_A: dma->regs.int_msk_a = value; break;
+ case DMA_INT_MSK_B: dma->regs.int_msk_b = value; break;
+ case DMA_INT_SRC_A: dma->regs.int_src_a = value; break;
+ case DMA_INT_SRC_B: dma->regs.int_src_b = value; break;
+ default:
+ fprintf( stderr, "dma_write32( 0x%"PRIxADDR" ): Illegal register\n",
+ addr + dma->baseaddr );
+ return;
+ }
+ } else {
+ /* case of per-channel registers */
+ unsigned chno = (addr - DMA_CH_BASE) / DMA_CH_SIZE;
+ struct dma_channel *channel = &(dma->ch[chno]);
+ channel->referenced = 1;
+ addr = (addr - DMA_CH_BASE) % DMA_CH_SIZE;
+ switch( addr ) {
+ case DMA_CSR: dma_write_ch_csr( &(dma->ch[chno]), value ); break;
+ case DMA_CH_SZ: channel->regs.sz = value; break;
+ case DMA_CH_A0: channel->regs.a0 = value; break;
+ case DMA_CH_AM0: channel->regs.am0 = value; break;
+ case DMA_CH_A1: channel->regs.a1 = value; break;
+ case DMA_CH_AM1: channel->regs.am1 = value; break;
+ case DMA_CH_DESC: channel->regs.desc = value; break;
+ case DMA_CH_SWPTR: channel->regs.swptr = value; break;
+ }
+ }
+}
+
+
+/* Write a channel CSR
+ * This ensures only the writable bits are modified.
+ */
+void dma_write_ch_csr( struct dma_channel *channel, unsigned long value )
+{
+ /* Check if we should *start* a transfer */
+ if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN ) &&
+ TEST_FLAG( value, DMA_CH_CSR, CH_EN ))
+ SCHED_ADD( dma_channel_clock, channel, 1 );
+ else if ( !TEST_FLAG( value, DMA_CH_CSR, CH_EN ) )
+ /* The CH_EN flag is clear, check if we have a transfer in progress and
+ * clear it */
+ SCHED_FIND_REMOVE( dma_channel_clock, channel );
+
+ /* Copy the writable bits to the channel CSR */
+ channel->regs.csr &= ~DMA_CH_CSR_WRITE_MASK;
+ channel->regs.csr |= value & DMA_CH_CSR_WRITE_MASK;
+}
+
+
+
+/* Clock tick for one channel on one DMA controller.
+ * This does the actual "DMA" operation.
+ * One chunk is transferred per clock.
+ */
+void dma_channel_clock( void *dat )
+{
+ struct dma_channel *channel = dat;
+
+ /* Do we need to abort? */
+ if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, STOP ) ) {
+ TRACE( "DMA: STOP requested\n" );
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN );
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY );
+ SET_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
+
+ if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INE_ERR ) &&
+ (channel->controller->regs.int_msk_a & channel->channel_mask) ) {
+ SET_FLAG( channel->regs.csr, DMA_CH_CSR, INT_ERR );
+ channel->controller->regs.int_src_a = channel->channel_mask;
+ report_interrupt( channel->controller->irq );
+ }
+
+ return;
+ }
+
+ /* In HW Handshake mode, only work when dma_req_i asserted */
+ if ( TEST_FLAG(channel->regs.csr, DMA_CH_CSR, MODE) && !channel->dma_req_i ) {
+ /* Reschedule */
+ SCHED_ADD( dma_channel_clock, dat, 1 );
+ return;
+ }
+
+ /* If this is the first cycle of the transfer, initialize our state */
+ if ( !TEST_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY ) ) {
+ TRACE( "DMA: Starting new transfer\n" );
+
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, DONE );
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
+ SET_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY );
+
+ /* If using linked lists, copy the appropriate fields to our registers */
+ if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, USE_ED ) )
+ dma_load_descriptor( channel );
+ else
+ channel->load_next_descriptor_when_done = 0;
+
+ /* Set our internal status */
+ dma_init_transfer( channel );
+
+ /* Might need to skip descriptor */
+ if ( CHANNEL_ND_I( channel ) ) {
+ TRACE( "DMA: dma_nd_i asserted before dma_req_i, skipping descriptor\n" );
+ dma_channel_terminate_transfer( channel, 0 );
+ return;
+ }
+ }
+
+ /* Transfer one word */
+ set_direct32( channel->destination, eval_direct32( channel->source, 0, 0 ),
+ 0, 0 );
+
+ /* Advance the source and destionation pointers */
+ masked_increase( &(channel->source), channel->source_mask );
+ masked_increase( &(channel->destination), channel->destination_mask );
+ ++ channel->words_transferred;
+
+ /* Have we finished a whole chunk? */
+ channel->dma_ack_o = (channel->words_transferred % channel->chunk_size == 0);
+
+ /* When done with a chunk, check for dma_nd_i */
+ if ( CHANNEL_ND_I( channel ) ) {
+ TRACE( "DMA: dma_nd_i asserted\n" );
+ dma_channel_terminate_transfer( channel, 0 );
+ return;
+ }
+
+ /* Are we done? */
+ if ( channel->words_transferred >= channel->total_size ) {
+ dma_channel_terminate_transfer( channel, 1 );
+ return;
+ }
+
+ /* Reschedule to transfer the next chunk */
+ SCHED_ADD( dma_channel_clock, dat, 1 );
+}
+
+
+/* Copy relevant valued from linked list descriptor to channel registers */
+void dma_load_descriptor( struct dma_channel *channel )
+{
+ unsigned long desc_csr = eval_direct32( channel->regs.desc + DMA_DESC_CSR, 0, 0 );
+
+ channel->load_next_descriptor_when_done = !TEST_FLAG( desc_csr, DMA_DESC_CSR, EOL );
+
+ ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, INC_SRC, TEST_FLAG( desc_csr, DMA_DESC_CSR, INC_SRC ) );
+ ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, INC_DST, TEST_FLAG( desc_csr, DMA_DESC_CSR, INC_DST ) );
+ ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, SRC_SEL, TEST_FLAG( desc_csr, DMA_DESC_CSR, SRC_SEL ) );
+ ASSIGN_FLAG( channel->regs.csr, DMA_CH_CSR, DST_SEL, TEST_FLAG( desc_csr, DMA_DESC_CSR, DST_SEL ) );
+
+ SET_FIELD( channel->regs.sz, DMA_CH_SZ, TOT_SZ, GET_FIELD( desc_csr, DMA_DESC_CSR, TOT_SZ ) );
+
+ channel->regs.a0 = eval_direct32( channel->regs.desc + DMA_DESC_ADR0, 0, 0 );
+ channel->regs.a1 = eval_direct32( channel->regs.desc + DMA_DESC_ADR1, 0, 0 );
+
+ channel->current_descriptor = channel->regs.desc;
+ channel->regs.desc = eval_direct32( channel->regs.desc + DMA_DESC_NEXT, 0, 0 );
+}
+
+
+/* Initialize internal parameters used to implement transfers */
+void dma_init_transfer( struct dma_channel *channel )
+{
+ channel->source = channel->regs.a0;
+ channel->destination = channel->regs.a1;
+ channel->source_mask = TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INC_SRC ) ? channel->regs.am0 : 0;
+ channel->destination_mask = TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INC_DST ) ? channel->regs.am1 : 0;
+ channel->total_size = GET_FIELD( channel->regs.sz, DMA_CH_SZ, TOT_SZ );
+ channel->chunk_size = GET_FIELD( channel->regs.sz, DMA_CH_SZ, CHK_SZ );
+ if ( !channel->chunk_size || (channel->chunk_size > channel->total_size) )
+ channel->chunk_size = channel->total_size;
+ channel->words_transferred = 0;
+}
+
+
+/* Take care of transfer termination */
+void dma_channel_terminate_transfer( struct dma_channel *channel, int generate_interrupt )
+{
+ TRACE( "DMA: Terminating transfer\n" );
+
+ /* Might be working in a linked list */
+ if ( channel->load_next_descriptor_when_done ) {
+ dma_load_descriptor( channel );
+ dma_init_transfer( channel );
+ /* Reschedule */
+ SCHED_ADD( dma_channel_clock, channel, 1 );
+ return;
+ }
+
+ /* Might be in auto-restart mode */
+ if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, ARS ) ) {
+ dma_init_transfer( channel );
+ return;
+ }
+
+ /* If needed, write amount of data transferred back to memory */
+ if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, SZ_WB ) &&
+ TEST_FLAG( channel->regs.csr, DMA_CH_CSR, USE_ED ) ) {
+ /* TODO: What should we write back? Doc says "total number of remaining bytes" !? */
+ unsigned long remaining_words = channel->total_size - channel->words_transferred;
+ SET_FIELD( channel->regs.sz, DMA_DESC_CSR, TOT_SZ, remaining_words );
+ }
+
+ /* Mark end of transfer */
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, CH_EN );
+ SET_FLAG( channel->regs.csr, DMA_CH_CSR, DONE );
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, ERR );
+ CLEAR_FLAG( channel->regs.csr, DMA_CH_CSR, BUSY );
+
+ /* If needed, generate interrupt */
+ if ( generate_interrupt ) {
+ /* TODO: Which channel should we interrupt? */
+ if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, INE_DONE ) &&
+ (channel->controller->regs.int_msk_a & channel->channel_mask) ) {
+ SET_FLAG( channel->regs.csr, DMA_CH_CSR, INT_DONE );
+ channel->controller->regs.int_src_a = channel->channel_mask;
+ report_interrupt( channel->controller->irq );
+ }
+ }
+}
+
+/* Utility function: Add 4 to a value with a mask */
+static void masked_increase( oraddr_t *value, unsigned long mask )
+{
+ *value = (*value & ~mask) | ((*value + 4) & mask);
+}
+
+/*-------------------------------------------[ DMA<->Peripheral interface ]---*/
+/*
+ * Simulation of control signals
+ * To be used by simulations for other devices, e.g. ethernet
+ */
+
+void set_dma_req_i( struct dma_channel *channel )
+{
+ channel->dma_req_i = 1;
+}
+
+void clear_dma_req_i( struct dma_channel *channel )
+{
+ channel->dma_req_i = 0;
+}
+
+void set_dma_nd_i( struct dma_channel *channel )
+{
+ channel->dma_nd_i = 1;
+}
+
+void clear_dma_nd_i( struct dma_channel *channel )
+{
+ channel->dma_nd_i = 0;
+}
+
+unsigned check_dma_ack_o( struct dma_channel *channel )
+{
+ return channel->dma_ack_o;
+}
+
+struct dma_channel *find_dma_controller_ch( unsigned controller,
+ unsigned channel )
+{
+ struct dma_controller *cur = dmas;
+
+ while( cur && controller ) {
+ cur = cur->next;
+ controller--;
+ }
+
+ if( !cur )
+ return NULL;
+
+ return &(cur->ch[channel]);
+}
+
+
+/*----------------------------------------------------[ DMA configuration ]---*/
+void dma_baseaddr(union param_val val, void *dat)
+{
+ struct dma_controller *dma = dat;
+ dma->baseaddr = val.addr_val;
+}
+
+void dma_irq(union param_val val, void *dat)
+{
+ struct dma_controller *dma = dat;
+ dma->irq = val.int_val;
+}
+
+void dma_vapi_id(union param_val val, void *dat)
+{
+ struct dma_controller *dma = dat;
+ dma->vapi_id = val.int_val;
+}
+
+void dma_enabled(union param_val val, void *dat)
+{
+ struct dma_controller *dma = dat;
+ dma->enabled = val.int_val;
+}
+
+void *dma_sec_start(void)
+{
+ struct dma_controller *new = malloc(sizeof(struct dma_controller));
+
+ if(!new) {
+ fprintf(stderr, "Peripheral DMA: Run out of memory\n");
+ exit(-1);
+ }
+
+ new->next = NULL;
+ new->enabled = 1;
+
+ return new;
+}
+
+void dma_sec_end(void *dat)
+{
+ struct dma_controller *dma = dat;
+ struct dma_controller *cur;
+ struct mem_ops ops;
+
+ if(!dma->enabled) {
+ free(dat);
+ return;
+ }
+
+ memset(&ops, 0, sizeof(struct mem_ops));
+
+ ops.readfunc32 = dma_read32;
+ ops.writefunc32 = dma_write32;
+ ops.read_dat32 = dat;
+ ops.write_dat32 = dat;
+
+ /* FIXME: Correct delay?? */
+ ops.delayr = 2;
+ ops.delayw = 2;
+
+ reg_mem_area( dma->baseaddr, DMA_ADDR_SPACE, 0, &ops );
+ reg_sim_reset( dma_reset, dat );
+ reg_sim_stat( dma_status, dat );
+
+ if(dmas) {
+ for(cur = dmas; cur->next; cur = cur->next);
+ cur->next = dma;
+ } else
+ dmas = dma;
+}
+
+void reg_dma_sec(void)
+{
+ struct config_section *sec = reg_config_sec("dma", dma_sec_start, dma_sec_end);
+
+ reg_config_param(sec, "irq", paramt_int, dma_irq);
+ reg_config_param(sec, "enabled", paramt_int, dma_enabled);
+ reg_config_param(sec, "baseaddr", paramt_addr, dma_baseaddr);
+ reg_config_param(sec, "vapi_id", paramt_addr, dma_vapi_id);
+}
Index: atadevice.h
===================================================================
--- atadevice.h (nonexistent)
+++ atadevice.h (revision 1765)
@@ -0,0 +1,199 @@
+/*
+ atahost.h -- ATA Host code simulation
+ Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ * Definitions for the Opencores ATA Controller Core, Device model
+ */
+
+#ifndef __OR1KSIM_ATAD_H
+#define __OR1KSIM_ATAD_H
+
+#include
+
+/* --- Register definitions --- */
+/* ----- ATA Registers */
+/* These are actually the memory locations where the ATA registers */
+/* can be found in the host system; i.e. as seen from the CPU. */
+/* However, this doesn't matter for the simulator. */
+#define ATA_ASR 0x78 /* Alternate Status Register (R) */
+#define ATA_CR 0x5c /* Command Register (W) */
+#define ATA_CHR 0x54 /* Cylinder High Register (R/W) */
+#define ATA_CLR 0x50 /* Cylinder Low Register (R/W) */
+#define ATA_DR 0x40 /* Data Register */
+#define ATA_DCR 0x78 /* Device Control Register (W) */
+#define ATA_DHR 0x58 /* Device/Head Register (R/W) */
+#define ATA_ERR 0x44 /* Error Register (R) */
+#define ATA_FR 0x44 /* Features Register (W) */
+#define ATA_SCR 0x48 /* Sector Count Register (R/W) */
+#define ATA_SNR 0x4c /* Sector Number Register (R/W) */
+#define ATA_SR 0x5c /* Status Register (R) */
+#define ATA_DA 0x7c /* Device Address Register (R) */
+ /* ATA/ATAPI-5 does not describe Device Status Register */
+
+/* -------------------------------------- */
+/* ----- ATA Device bit defenitions ----- */
+/* -------------------------------------- */
+
+/* ----- ATA (Alternate) Status Register */
+#define ATA_SR_BSY 0x80 /* Busy */
+#define ATA_SR_DRDY 0x40 /* Device Ready */
+#define ATA_SR_DF 0x20 /* Device Fault */
+#define ATA_SR_DSC 0x10 /* Device Seek Complete */
+#define ATA_SR_DRQ 0x08 /* Data Request */
+#define ATA_SR_COR 0x04 /* Corrected data (obsolete) */
+#define ATA_SR_IDX 0x02 /* (obsolete) */
+#define ATA_SR_ERR 0x01 /* Error */
+
+/* ----- ATA Device Control Register */
+ /* bits 7-3 are reserved */
+#define ATA_DCR_RST 0x04 /* Software reset (RST=1, reset) */
+#define ATA_DCR_IEN 0x02 /* Interrupt Enable (IEN=0, enabled) */
+ /* always write a '0' to bit0 */
+
+/* ----- ATA Device Address Register */
+/* All values in this register are one's complement (i.e. inverted) */
+#define ATA_DAR_WTG 0x40 /* Write Gate */
+#define ATA_DAR_H 0x3c /* Head Select */
+#define ATA_DAR_DS1 0x02 /* Drive select 1 */
+#define ATA_DAR_DS0 0x01 /* Drive select 0 */
+
+/* ----- Device/Head Register */
+#define ATA_DHR_LBA 0x40 /* LBA/CHS mode ('1'=LBA mode) */
+#define ATA_DHR_DEV 0x10 /* Device ('0'=dev0, '1'=dev1) */
+#define ATA_DHR_H 0x0f /* Head Select */
+
+/* ----- Error Register */
+#define ATA_ERR_BBK 0x80 /* Bad Block */
+#define ATA_ERR_UNC 0x40 /* Uncorrectable Data Error */
+#define ATA_ERR_IDNF 0x10 /* ID Not Found */
+#define ATA_ERR_ABT 0x04 /* Aborted Command */
+#define ATA_ERR_TON 0x02 /* Track0 Not Found */
+#define ATA_ERR_AMN 0x01 /* Address Mark Not Found */
+
+/* -------------------------- */
+/* ----- Device Defines ----- */
+/* -------------------------- */
+
+/* types for hard disk simulation */
+#define TYPE_NO_CONNECT 0
+#define TYPE_FILE 1
+#define TYPE_LOCAL 2
+
+
+/* ----------------------------- */
+/* ----- Statemachine defines -- */
+/* ----------------------------- */
+#define ATA_STATE_IDLE 0x00
+#define ATA_STATE_SW_RST 0x01
+#define ATA_STATE_HW_RST 0x02
+
+
+/* ---------------------------- */
+/* ----- Structs ----- */
+/* ---------------------------- */
+typedef struct{
+
+ /******* Housekeeping *****************************************/
+ struct {
+ /* device number */
+ int dev;
+
+ /* current PIO mode */
+ int pio_mode;
+
+ /* current DMA mode */
+ int dma_mode;
+
+ /* databuffer */
+ unsigned short dbuf[4096];
+ unsigned short *dbuf_ptr;
+ unsigned short dbuf_cnt;
+
+ /* current statemachine state */
+ int state;
+
+ /* current CHS translation settings */
+ unsigned int heads_per_cylinder;
+ unsigned int sectors_per_track;
+ } internals;
+
+
+ /******* ATA Device Registers *********************************/
+ struct {
+ unsigned char command;
+ unsigned char cylinder_low;
+ unsigned char cylinder_high;
+ unsigned char device_control;
+ unsigned char device_head;
+ unsigned char error;
+ unsigned char features;
+ unsigned char sector_count;
+ unsigned char sector_number;
+ unsigned char status;
+
+ short dataport_i;
+ } regs;
+
+ /******** ata device output signals **************************/
+ struct {
+ int iordy;
+ int intrq;
+ int dmarq;
+ int pdiagi, pdiago;
+ int daspi, daspo;
+ } sigs;
+
+ /******** simulator settings **********************************/
+ /* simulate ata-device */
+ char *file; /* Filename (if type == FILE) */
+ FILE *stream; /* stream where the simulated device connects to*/
+ int type; /* Simulate device using */
+ /* NO_CONNECT: no device connected (dummy) */
+ /* FILE : a file */
+ /* LOCAL : a local stream, e.g./dev/hda1 */
+ unsigned long size; /* size in MB of the simulated device */
+ int packet; /* device implements PACKET command set */
+} ata_device;
+
+typedef struct{
+ ata_device device0, device1;
+} ata_devices;
+
+
+/* all devices */
+void ata_devices_init(ata_devices *devices);
+void ata_devices_hw_reset(ata_devices *devices, int reset_signal);
+short ata_devices_read(ata_devices *devices, char adr);
+void ata_devices_write(ata_devices *devices, char adr, short value);
+
+/* single device */
+void ata_device_init(ata_device *device, int dev);
+void ata_device_hw_reset(ata_device *device, int reset_signal, int daspo, int pdiagi, int daspi);
+void ata_device_do_control_register(ata_device *device);
+void ata_device_do_command_register(ata_device *device);
+void ata_device_write(ata_device *device, char adr, short value);
+
+/* housekeeping routines */
+FILE *open_file(unsigned long *size, const char *filename);
+FILE *open_local(void);
+
+
+#endif
atadevice.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: mc.h
===================================================================
--- mc.h (nonexistent)
+++ mc.h (revision 1765)
@@ -0,0 +1,111 @@
+/* mc.h -- Simulation of Memory Controller
+ Copyright (C) 2001 by Marko Mlinar, markom@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* Prototypes */
+#ifndef __MC_H
+#define __MC_H
+
+#define N_CE (8)
+
+#define MC_CSR (0x00)
+#define MC_POC (0x04)
+#define MC_BA_MASK (0x08)
+#define MC_CSC(i) (0x10 + (i) * 8)
+#define MC_TMS(i) (0x14 + (i) * 8)
+
+#define MC_ADDR_SPACE (MC_CSC(N_CE))
+
+/* POC register field definition */
+#define MC_POC_EN_BW_OFFSET 0
+#define MC_POC_EN_BW_WIDTH 2
+#define MC_POC_EN_MEMTYPE_OFFSET 2
+#define MC_POC_EN_MEMTYPE_WIDTH 2
+
+/* CSC register field definition */
+#define MC_CSC_EN_OFFSET 0
+#define MC_CSC_MEMTYPE_OFFSET 1
+#define MC_CSC_MEMTYPE_WIDTH 2
+#define MC_CSC_BW_OFFSET 4
+#define MC_CSC_BW_WIDTH 2
+#define MC_CSC_MS_OFFSET 6
+#define MC_CSC_MS_WIDTH 2
+#define MC_CSC_WP_OFFSET 8
+#define MC_CSC_BAS_OFFSET 9
+#define MC_CSC_KRO_OFFSET 10
+#define MC_CSC_PEN_OFFSET 11
+#define MC_CSC_SEL_OFFSET 16
+#define MC_CSC_SEL_WIDTH 8
+
+#define MC_CSC_MEMTYPE_SDRAM 0
+#define MC_CSC_MEMTYPE_SSRAM 1
+#define MC_CSC_MEMTYPE_ASYNC 2
+#define MC_CSC_MEMTYPE_SYNC 3
+
+#define MC_CSR_VALID 0xFF000703LU
+#define MC_POC_VALID 0x0000000FLU
+#define MC_BA_MASK_VALID 0x000003FFLU
+#define MC_CSC_VALID 0x00FF0FFFLU
+#define MC_TMS_SDRAM_VALID 0x0FFF83FFLU
+#define MC_TMS_SSRAM_VALID 0x00000000LU
+#define MC_TMS_ASYNC_VALID 0x03FFFFFFLU
+#define MC_TMS_SYNC_VALID 0x01FFFFFFLU
+#define MC_TMS_VALID 0xFFFFFFFFLU /* reg test compat. */
+
+/* TMS register field definition SDRAM */
+#define MC_TMS_SDRAM_TRFC_OFFSET 24
+#define MC_TMS_SDRAM_TRFC_WIDTH 4
+#define MC_TMS_SDRAM_TRP_OFFSET 20
+#define MC_TMS_SDRAM_TRP_WIDTH 4
+#define MC_TMS_SDRAM_TRCD_OFFSET 17
+#define MC_TMS_SDRAM_TRCD_WIDTH 4
+#define MC_TMS_SDRAM_TWR_OFFSET 15
+#define MC_TMS_SDRAM_TWR_WIDTH 2
+#define MC_TMS_SDRAM_WBL_OFFSET 9
+#define MC_TMS_SDRAM_OM_OFFSET 7
+#define MC_TMS_SDRAM_OM_WIDTH 2
+#define MC_TMS_SDRAM_CL_OFFSET 4
+#define MC_TMS_SDRAM_CL_WIDTH 3
+#define MC_TMS_SDRAM_BT_OFFSET 3
+#define MC_TMS_SDRAM_BL_OFFSET 0
+#define MC_TMS_SDRAM_BL_WIDTH 3
+
+/* TMS register field definition ASYNC */
+#define MC_TMS_ASYNC_TWWD_OFFSET 20
+#define MC_TMS_ASYNC_TWWD_WIDTH 6
+#define MC_TMS_ASYNC_TWD_OFFSET 16
+#define MC_TMS_ASYNC_TWD_WIDTH 4
+#define MC_TMS_ASYNC_TWPW_OFFSET 12
+#define MC_TMS_ASYNC_TWPW_WIDTH 4
+#define MC_TMS_ASYNC_TRDZ_OFFSET 8
+#define MC_TMS_ASYNC_TRDZ_WIDTH 4
+#define MC_TMS_ASYNC_TRDV_OFFSET 0
+#define MC_TMS_ASYNC_TRDV_WIDTH 8
+
+/* TMS register field definition SYNC */
+#define MC_TMS_SYNC_TTO_OFFSET 16
+#define MC_TMS_SYNC_TTO_WIDTH 9
+#define MC_TMS_SYNC_TWR_OFFSET 12
+#define MC_TMS_SYNC_TWR_WIDTH 4
+#define MC_TMS_SYNC_TRDZ_OFFSET 8
+#define MC_TMS_SYNC_TRDZ_WIDTH 4
+#define MC_TMS_SYNC_TRDV_OFFSET 0
+#define MC_TMS_SYNC_TRDV_WIDTH 8
+
+#endif
mc.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: atahost.h
===================================================================
--- atahost.h (nonexistent)
+++ atahost.h (revision 1765)
@@ -0,0 +1,152 @@
+/*
+ atahost.h -- ATA Host code simulation
+ Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ * Definitions for the Opencores ATA Host Controller Core
+ */
+
+#ifndef __OR1KSIM_ATAH_H
+#define __OR1KSIM_ATAH_H
+
+#include "atadevice.h"
+
+/* --- Register definitions --- */
+
+/* ----- Core Registers */
+#define ATA_CTRL 0x00 /* Control register */
+#define ATA_STAT 0x04 /* Status register */
+#define ATA_PCTR 0x08 /* PIO command timing register */
+#define ATA_PFTR0 0x0c /* PIO Fast Timing register Device0 */
+#define ATA_PFTR1 0x10 /* PIO Fast Timing register Device1 */
+#define ATA_DTR0 0x14 /* DMA Timing register Device2 */
+#define ATA_DTR1 0x18 /* DMA Timing register Device1 */
+#define ATA_TXB 0x3c /* DMA Transmit buffer */
+#define ATA_RXB 0x3c /* DMA Receive buffer */
+
+
+/* ---------------------------- */
+/* ----- Bits definitions ----- */
+/* ---------------------------- */
+
+/* ----- Core Control register */
+ /* bits 31-16 are reserved */
+#define ATA_DMA_EN (0<<15) /* DMAen, DMA enable bit */
+ /* bit 14 is reserved */
+#define ATA_DMA_WR (1<<14) /* DMA Write transaction */
+#define ATA_DMA_RD (0<<14) /* DMA Read transaction */
+ /* bits 13-10 are reserved */
+#define ATA_BELEC1 (1<< 9) /* Big-Little endian conversion */
+ /* enable bit for Device1 */
+#define ATA_BELEC0 (1<< 8) /* Big-Little endian conversion */
+ /* enable bit for Device0 */
+#define ATA_IDE_EN (1<< 7) /* IDE core enable bit */
+#define ATA_FTE1 (1<< 6) /* Device1 Fast PIO Timing Enable bit */
+#define ATA_FTE0 (1<< 5) /* Device0 Fast PIO Timing Enable bit */
+#define ATA_PWPP (1<< 4) /* PIO Write Ping-Pong Enable bit */
+#define ATA_IORDY_FTE1 (1<< 3) /* Device1 Fast PIO Timing IORDY */
+ /* enable bit */
+#define ATA_IORDY_FTE0 (1<< 2) /* Device0 Fast PIO Timing IORDY */
+ /* enable bit */
+#define ATA_IORDY (1<< 1) /* PIO Command Timing IORDY enable bit*/
+#define ATA_RST (1<< 0) /* ATA Reset bit */
+
+/* ----- Core Status register */
+#define ATA_DEVID 0xf0000000 /* bits 31-28 Device-ID */
+#define ATA_REVNO 0x0f000000 /* bits 27-24 Revision number */
+ /* bits 23-16 are reserved */
+#define ATA_DMA_TIP (1<<15) /* DMA Transfer in progress */
+ /* bits 14-10 are reserved */
+#define ATA_DRBE (1<<10) /* DMA Receive buffer empty */
+#define ATA_DTBF (1<< 9) /* DMA Transmit buffer full */
+#define ATA_DMARQ (1<< 8) /* DMARQ Line status */
+#define ATA_PIO_TIP (1<< 7 /* PIO Transfer in progress */
+#define ATA_PWPPF (1<< 6) /* PIO write ping-pong full */
+ /* bits 5-1 are reserved */
+#define ATA_IDEIS (1<< 0) /* IDE Interrupt status */
+
+
+/* ----- Core Timing registers */
+#define ATA_TEOC 24 /* End of cycle time DMA/PIO */
+#define ATA_T4 16 /* DIOW- data hold time PIO */
+#define ATA_T2 8 /* DIOR-/DIOW- pulse width PIO */
+#define ATA_TD 8 /* DIOR-/DIOW- pulse width DMA */
+#define ATA_T1 0 /* Address valid to DIOR-/DIOW- PIO */
+#define ATA_TM 0 /* CS[1:0]valid to DIOR-/DIOW- DMA */
+
+
+/* ----------------------------- */
+/* ----- Simulator defines ----- */
+/* ----------------------------- */
+#define ATA_ADDR_SPACE 0x80
+
+
+/* ---------------------------- */
+/* ----- Structs ----- */
+/* ---------------------------- */
+typedef struct{
+ /* Is peripheral enabled? */
+ int enabled;
+
+ /* Base address in memory */
+ oraddr_t baseaddr;
+
+ /* Registered memory area */
+ struct dev_memarea *mem;
+
+ /* Which IRQ to generate */
+ int irq;
+
+ /* ata host registers */
+ struct {
+ int ctrl;
+ int stat;
+ int pctr;
+ int pftr0;
+ int pftr1;
+ int dtr0;
+ int dtr1;
+ int txb;
+ int rxb;
+ } regs;
+
+ /* connected ATA devices (slaves) */
+ ata_devices devices;
+} ata_host;
+
+/* ---------------------------- */
+/* ----- Prototypes ----- */
+/* ---------------------------- */
+void ata_reset(void *dat);
+uint32_t ata_read32( oraddr_t addr, void *dat );
+void ata_write32( oraddr_t addr, uint32_t value, void *dat );
+void ata_status(void *dat);
+
+
+/* ---------------------------- */
+/* ----- Macros ----- */
+/* ---------------------------- */
+#define is_ata_hostadr(adr) (!(adr & 0x40))
+
+// FIXME
+#define ata_pio_delay(pioreg) ( (((pioreg >> ATA_T1) & 0xff) +1) + (((pioreg >> ATA_T2) & 0xff) +1) + (((pioreg >> ATA_T4) & 0xff) +1) +1 )
+#define ata_dma_delay(dmareg) ( (((dmareg >> ATA_TD) & 0xff) +1) + (((pioreg >> ATA_TM) & 0xff) +1) +1 )
+
+#endif
atahost.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: Makefile.am
===================================================================
--- Makefile.am (nonexistent)
+++ Makefile.am (revision 1765)
@@ -0,0 +1,37 @@
+# Makefile -- Makefile for peripherals simulation
+# Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
+#
+# This file is part of OpenRISC 1000 Architectural Simulator.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#
+
+SUBDIRS = channels
+
+noinst_LIBRARIES = libperipheral.a
+libperipheral_a_SOURCES = \
+16450.c \
+dma.c \
+mc.c \
+eth.c \
+crc32.c \
+gpio.c \
+vga.c \
+fb.c \
+ps2kbd.c \
+atahost.c \
+atadevice.c \
+atadevice_cmdi.c \
+memory.c
Index: ethernet_i.h
===================================================================
--- ethernet_i.h (nonexistent)
+++ ethernet_i.h (revision 1765)
@@ -0,0 +1,225 @@
+/* ethernet_i.h -- Definition of internal types and structures for Ethernet MAC
+ Copyright (C) 2001 Erez Volk, erez@mailandnews.comopencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __OR1KSIM_PERIPHERAL_ETHERNET_I_H
+#define __OR1KSIM_PERIPHERAL_ETHERNET_I_H
+
+#include "ethernet.h"
+#include "config.h"
+
+#if HAVE_ETH_PHY
+#include
+#endif /* HAVE_ETH_PHY */
+#include
+#include
+#include
+
+/*
+ * Ethernet protocol definitions
+ */
+#if HAVE_NET_ETHERNET_H
+# include
+#elif HAVE_SYS_ETHERNET_H
+# include
+#ifndef ETHER_ADDR_LEN
+#define ETHER_ADDR_LEN ETHERADDRL
+#endif
+#ifndef ETHER_HDR_LEN
+#define ETHER_HDR_LEN sizeof(struct ether_header)
+#endif
+#else /* !HAVE_NET_ETHERNET_H && !HAVE_SYS_ETHERNET_H -*/
+
+#include
+
+#ifdef __CYGWIN__
+/* define some missing cygwin defines.
+ *
+ * NOTE! there is no nonblocking socket option implemented in cygwin.dll
+ * so defining MSG_DONTWAIT is just (temporary) workaround !!!
+ */
+#define MSG_DONTWAIT 0x40
+#define ETH_HLEN 14
+#endif /* __CYGWIN__ */
+
+#define ETH_ALEN 6
+
+struct ether_addr
+{
+ u_int8_t ether_addr_octet[ETH_ALEN];
+};
+
+struct ether_header
+{
+ u_int8_t ether_dhost[ETH_ALEN]; /* destination eth addr */
+ u_int8_t ether_shost[ETH_ALEN]; /* source ether addr */
+ u_int16_t ether_type; /* packet type ID field */
+};
+
+/* Ethernet protocol ID's */
+#define ETHERTYPE_PUP 0x0200 /* Xerox PUP */
+#define ETHERTYPE_IP 0x0800 /* IP */
+#define ETHERTYPE_ARP 0x0806 /* Address resolution */
+#define ETHERTYPE_REVARP 0x8035 /* Reverse ARP */
+
+#define ETHER_ADDR_LEN ETH_ALEN /* size of ethernet addr */
+#define ETHER_TYPE_LEN 2 /* bytes in type field */
+#define ETHER_CRC_LEN 4 /* bytes in CRC field */
+#define ETHER_HDR_LEN ETH_HLEN /* total octets in header */
+#define ETHER_MIN_LEN (ETH_ZLEN + ETHER_CRC_LEN) /* min packet length */
+#define ETHER_MAX_LEN (ETH_FRAME_LEN + ETHER_CRC_LEN) /* max packet length */
+
+/* make sure ethenet length is valid */
+#define ETHER_IS_VALID_LEN(foo) \
+ ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN)
+
+/*
+ * The ETHERTYPE_NTRAILER packet types starting at ETHERTYPE_TRAIL have
+ * (type-ETHERTYPE_TRAIL)*512 bytes of data followed
+ * by an ETHER type (as given above) and then the (variable-length) header.
+ */
+#define ETHERTYPE_TRAIL 0x1000 /* Trailer packet */
+#define ETHERTYPE_NTRAILER 16
+
+#define ETHERMTU ETH_DATA_LEN
+#define ETHERMIN (ETHER_MIN_LEN-ETHER_HDR_LEN-ETHER_CRC_LEN)
+
+#endif /* HAVE_NET_ETHERNET_H */
+
+
+/*
+ * Implementatino of Ethernet MAC Registers and State
+ */
+#define ETH_TXSTATE_IDLE 0
+#define ETH_TXSTATE_WAIT4BD 10
+#define ETH_TXSTATE_READFIFO 20
+#define ETH_TXSTATE_TRANSMIT 30
+
+#define ETH_RXSTATE_IDLE 0
+#define ETH_RXSTATE_WAIT4BD 10
+#define ETH_RXSTATE_RECV 20
+#define ETH_RXSTATE_WRITEFIFO 30
+
+#define ETH_RTX_FILE 0
+#define ETH_RTX_SOCK 1
+#define ETH_RTX_VAPI 2
+
+#define ETH_MAXPL 0x10000
+
+enum { ETH_VAPI_DATA = 0,
+ ETH_VAPI_CTRL,
+ ETH_NUM_VAPI_IDS };
+
+struct eth_device
+{
+ /* Is peripheral enabled */
+ int enabled;
+
+ /* Base address in memory */
+ oraddr_t baseaddr;
+
+ /* Which DMA controller is this MAC connected to */
+ unsigned dma;
+ unsigned tx_channel;
+ unsigned rx_channel;
+
+ /* Our address */
+ unsigned char mac_address[ETHER_ADDR_LEN];
+
+ /* interrupt line */
+ unsigned long mac_int;
+
+ /* VAPI ID */
+ unsigned long base_vapi_id;
+
+ /* RX and TX file names and handles */
+ char *rxfile, *txfile;
+ int txfd;
+ int rxfd;
+ off_t loopback_offset;
+
+ /* Socket interface name */
+ char *sockif;
+
+ int rtx_sock;
+ int rtx_type;
+ struct ifreq ifr;
+ fd_set rfds, wfds;
+
+ /* Current TX state */
+ struct
+ {
+ unsigned long state;
+ unsigned long bd_index;
+ unsigned long bd;
+ unsigned long bd_addr;
+ unsigned working, waiting_for_dma, error;
+ long packet_length;
+ unsigned minimum_length, maximum_length;
+ unsigned add_crc;
+ unsigned crc_dly;
+ unsigned long crc_value;
+ long bytes_left, bytes_sent;
+ } tx;
+
+ /* Current RX state */
+ struct
+ {
+ unsigned long state;
+ unsigned long bd_index;
+ unsigned long bd;
+ unsigned long bd_addr;
+ int fd;
+ off_t *offset;
+ unsigned working, error, waiting_for_dma;
+ long packet_length, bytes_read, bytes_left;
+ } rx;
+
+ /* Visible registers */
+ struct
+ {
+ unsigned long moder;
+ unsigned long int_source;
+ unsigned long int_mask;
+ unsigned long ipgt;
+ unsigned long ipgr1;
+ unsigned long ipgr2;
+ unsigned long packetlen;
+ unsigned long collconf;
+ unsigned long tx_bd_num;
+ unsigned long controlmoder;
+ unsigned long miimoder;
+ unsigned long miicommand;
+ unsigned long miiaddress;
+ unsigned long miitx_data;
+ unsigned long miirx_data;
+ unsigned long miistatus;
+ unsigned long hash0;
+ unsigned long hash1;
+
+ /* Buffer descriptors */
+ unsigned long bd_ram[ETH_BD_SPACE / 4];
+ } regs;
+
+ unsigned char rx_buff[ETH_MAXPL];
+ unsigned char tx_buff[ETH_MAXPL];
+ unsigned char lo_buff[ETH_MAXPL];
+};
+
+#endif /* __OR1KSIM_PERIPHERAL_ETHERNET_I_H */
Index: dma.h
===================================================================
--- dma.h (nonexistent)
+++ dma.h (revision 1765)
@@ -0,0 +1,99 @@
+/* dma.h -- Definition of DMA<->peripheral interface
+ Copyright (C) 2001 by Erez Volk, erez@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "dma_defs.h"
+
+/* Implementation of DMA Channel Registers and State */
+struct dma_channel
+{
+ /* The controller we belong to */
+ struct dma_controller *controller;
+
+ /* Our channel number and bit mask */
+ unsigned channel_number;
+ unsigned long channel_mask;
+
+ /* Used for dump, to save dumping all 32 channels */
+ unsigned referenced;
+
+ /* Inner state of transfer etc. */
+ unsigned load_next_descriptor_when_done;
+ unsigned long current_descriptor;
+ oraddr_t source, destination, source_mask, destination_mask;
+ unsigned long chunk_size, total_size, words_transferred;
+
+ /* The interface registers */
+ struct
+ {
+ unsigned long csr;
+ unsigned long sz;
+ unsigned long a0;
+ unsigned long am0;
+ unsigned long a1;
+ unsigned long am1;
+ unsigned long desc;
+ unsigned long swptr;
+ } regs;
+
+ /* Some control signals */
+ unsigned dma_req_i;
+ unsigned dma_ack_o;
+ unsigned dma_nd_i;
+};
+
+
+/* Implementation of DMA Controller Registers and State */
+struct dma_controller
+{
+ /* Is peripheral enabled */
+ int enabled;
+
+ /* Base address in memory */
+ oraddr_t baseaddr;
+
+ /* Which interrupt number we generate */
+ unsigned irq;
+
+ /* VAPI id */
+ int vapi_id;
+
+ /* Controller Registers */
+ struct
+ {
+ unsigned long csr;
+ unsigned long int_msk_a;
+ unsigned long int_msk_b;
+ unsigned long int_src_a;
+ unsigned long int_src_b;
+ } regs;
+
+ /* Channels */
+ struct dma_channel ch[DMA_NUM_CHANNELS];
+
+ struct dma_controller *next;
+};
+
+void set_dma_req_i( struct dma_channel *channel );
+void clear_dma_req_i( struct dma_channel *channel );
+void set_dma_nd_i( struct dma_channel *channel );
+void clear_dma_nd_i( struct dma_channel *channel );
+unsigned check_dma_ack_o( struct dma_channel *channel );
+struct dma_channel *find_dma_controller_ch( unsigned controller,
+ unsigned channel );
Index: gpio_i.h
===================================================================
--- gpio_i.h (nonexistent)
+++ gpio_i.h (revision 1765)
@@ -0,0 +1,83 @@
+/* gpio_i.h -- Definition of internal types and structures for GPIO code
+ Copyright (C) 2001 Erez Volk, erez@mailandnews.comopencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __OR1KSIM_PERIPHERAL_GPIO_I_H
+#define __OR1KSIM_PERIPHERAL_GPIO_I_H
+
+#include "gpio.h"
+#include "config.h"
+
+/*
+ * The various VAPI IDs each GPIO device has
+ */
+enum { GPIO_VAPI_DATA = 0,
+ GPIO_VAPI_AUX,
+ GPIO_VAPI_CLOCK,
+ GPIO_VAPI_RGPIO_OE,
+ GPIO_VAPI_RGPIO_INTE,
+ GPIO_VAPI_RGPIO_PTRIG,
+ GPIO_VAPI_RGPIO_AUX,
+ GPIO_VAPI_RGPIO_CTRL,
+ GPIO_NUM_VAPI_IDS };
+
+
+/*
+ * Implementatino of GPIO Code Registers and State
+ */
+struct gpio_device
+{
+ /* Is peripheral enabled */
+ int enabled;
+
+ /* Base address in memory */
+ oraddr_t baseaddr;
+
+ /* Which IRQ to generate */
+ int irq;
+
+ /* Which GPIO is this? */
+ unsigned gpio_number;
+
+ /* VAPI IDs */
+ unsigned long base_vapi_id;
+
+ /* Auxiliary inputs */
+ unsigned long auxiliary_inputs;
+
+ /* Visible registers */
+ struct
+ {
+ unsigned long in;
+ unsigned long out;
+ unsigned long oe;
+ unsigned long inte;
+ unsigned long ptrig;
+ unsigned long aux;
+ unsigned long ctrl;
+ unsigned long ints;
+
+ int external_clock;
+ } curr, next;
+};
+
+
+
+
+#endif /* __OR1KSIM_PERIPHERAL_GPIO_I_H */
Index: gpio.h
===================================================================
--- gpio.h (nonexistent)
+++ gpio.h (revision 1765)
@@ -0,0 +1,44 @@
+/* gpio.h -- Definition of types and structures for the GPIO code
+ Copyright (C) 2001 Erez Volk, erez@mailandnews.comopencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __OR1KSIM_PERIPHERAL_GPIO_H
+#define __OR1KSIM_PERIPHERAL_GPIO_H
+
+/* Address space required by one GPIO */
+#define GPIO_ADDR_SPACE 0x20
+
+/* Relative Register Addresses */
+#define RGPIO_IN 0x00
+#define RGPIO_OUT 0x04
+#define RGPIO_OE 0x08
+#define RGPIO_INTE 0x0C
+#define RGPIO_PTRIG 0x10
+#define RGPIO_AUX 0x14
+#define RGPIO_CTRL 0x18
+#define RGPIO_INTS 0x1C
+
+/* Fields inside RGPIO_CTRL */
+#define RGPIO_CTRL_ECLK 0x00000001
+#define RGPIO_CTRL_NEC 0x00000002
+#define RGPIO_CTRL_INTE 0x00000004
+#define RGPIO_CTRL_INTS 0x00000008
+
+
+#endif /* __OR1KSIM_PERIPHERAL_GPIO_H */
Index: ethernet.h
===================================================================
--- ethernet.h (nonexistent)
+++ ethernet.h (revision 1765)
@@ -0,0 +1,168 @@
+/* ethernet.h -- Definition of types and structures for Ethernet MAC
+ Copyright (C) 2001 Erez Volk, erez@mailandnews.comopencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __OR1KSIM_PERIPHERAL_ETHERNET_H
+#define __OR1KSIM_PERIPHERAL_ETHERNET_H
+
+/* Address space required by one Ethernet MAC */
+#define ETH_ADDR_SPACE 0x1000
+
+/* Relative Register Addresses */
+#define ETH_MODER (4 * 0x00)
+#define ETH_INT_SOURCE (4 * 0x01)
+#define ETH_INT_MASK (4 * 0x02)
+#define ETH_IPGT (4 * 0x03)
+#define ETH_IPGR1 (4 * 0x04)
+#define ETH_IPGR2 (4 * 0x05)
+#define ETH_PACKETLEN (4 * 0x06)
+#define ETH_COLLCONF (4 * 0x07)
+#define ETH_TX_BD_NUM (4 * 0x08)
+#define ETH_CTRLMODER (4 * 0x09)
+#define ETH_MIIMODER (4 * 0x0A)
+#define ETH_MIICOMMAND (4 * 0x0B)
+#define ETH_MIIADDRESS (4 * 0x0C)
+#define ETH_MIITX_DATA (4 * 0x0D)
+#define ETH_MIIRX_DATA (4 * 0x0E)
+#define ETH_MIISTATUS (4 * 0x0F)
+#define ETH_MAC_ADDR0 (4 * 0x10)
+#define ETH_MAC_ADDR1 (4 * 0x11)
+#define ETH_HASH0 (4 * 0x12)
+#define ETH_HASH1 (4 * 0x13)
+
+/* Where BD's are stored */
+#define ETH_BD_BASE 0x400
+#define ETH_BD_COUNT 0x100
+#define ETH_BD_SPACE (4 * ETH_BD_COUNT)
+
+/* Where to point DMA to transmit/receive */
+#define ETH_DMA_RX_TX 0x800
+
+/* Field definitions for MODER */
+#define ETH_MODER_DMAEN_OFFSET 17
+#define ETH_MODER_RECSMALL_OFFSET 16
+#define ETH_MODER_PAD_OFFSET 15
+#define ETH_MODER_HUGEN_OFFSET 14
+#define ETH_MODER_CRCEN_OFFSET 13
+#define ETH_MODER_DLYCRCEN_OFFSET 12
+#define ETH_MODER_RST_OFFSET 11
+#define ETH_MODER_FULLD_OFFSET 10
+#define ETH_MODER_EXDFREN_OFFSET 9
+#define ETH_MODER_NOBCKOF_OFFSET 8
+#define ETH_MODER_LOOPBCK_OFFSET 7
+#define ETH_MODER_IFG_OFFSET 6
+#define ETH_MODER_PRO_OFFSET 5
+#define ETH_MODER_IAM_OFFSET 4
+#define ETH_MODER_BRO_OFFSET 3
+#define ETH_MODER_NOPRE_OFFSET 2
+#define ETH_MODER_TXEN_OFFSET 1
+#define ETH_MODER_RXEN_OFFSET 0
+
+/* Field definitions for INT_SOURCE */
+#define ETH_INT_SOURCE_RXC_OFFSET 6
+#define ETH_INT_SOURCE_TXC_OFFSET 5
+#define ETH_INT_SOURCE_BUSY_OFFSET 4
+#define ETH_INT_SOURCE_RXE_OFFSET 3
+#define ETH_INT_SOURCE_RXB_OFFSET 2
+#define ETH_INT_SOURCE_TXE_OFFSET 1
+#define ETH_INT_SOURCE_TXB_OFFSET 0
+
+/* Field definitions for INT_MASK */
+#define ETH_INT_MASK_RXC_M_OFFSET 6
+#define ETH_INT_MASK_TXC_M_OFFSET 5
+#define ETH_INT_MASK_BUSY_M_OFFSET 4
+#define ETH_INT_MASK_RXE_M_OFFSET 3
+#define ETH_INT_MASK_RXB_M_OFFSET 2
+#define ETH_INT_MASK_TXE_M_OFFSET 1
+#define ETH_INT_MASK_TXB_M_OFFSET 0
+
+/* Field definitions for PACKETLEN */
+#define ETH_PACKETLEN_MINFL_OFFSET 16
+#define ETH_PACKETLEN_MINFL_WIDTH 16
+#define ETH_PACKETLEN_MAXFL_OFFSET 0
+#define ETH_PACKETLEN_MAXFL_WIDTH 16
+
+/* Field definitions for COLLCONF */
+#define ETH_COLLCONF_MAXRET_OFFSET 16
+#define ETH_COLLCONF_MAXRET_WIDTH 4
+#define ETH_COLLCONF_COLLVALID_OFFSET 0
+#define ETH_COLLCONF_COLLVALID_WIDTH 6
+
+/* Field definitions for CTRLMODER */
+#define ETH_CMODER_TXFLOW_OFFSET 2
+#define ETH_CMODER_RXFLOW_OFFSET 1
+#define ETH_CMODER_PASSALL_OFFSET 0
+
+/* Field definitions for MIIMODER */
+#define ETH_MIIMODER_MRST_OFFSET 9
+#define ETH_MIIMODER_NOPRE_OFFSET 8
+#define ETH_MIIMODER_CLKDIV_OFFSET 0
+#define ETH_MIIMODER_CLKDIV_WIDTH 8
+
+/* Field definitions for MIICOMMAND */
+#define ETH_MIICOMM_WCDATA_OFFSET 2
+#define ETH_MIICOMM_RSTAT_OFFSET 1
+#define ETH_MIICOMM_SCANS_OFFSET 0
+
+/* Field definitions for MIIADDRESS */
+#define ETH_MIIADDR_RGAD_OFFSET 8
+#define ETH_MIIADDR_RGAD_WIDTH 5
+#define ETH_MIIADDR_FIAD_OFFSET 0
+#define ETH_MIIADDR_FIAD_WIDTH 5
+
+/* Field definitions for MIISTATUS */
+#define ETH_MIISTAT_NVALID_OFFSET 1
+#define ETH_MIISTAT_BUSY_OFFSET 1
+#define ETH_MIISTAT_FAIL_OFFSET 0
+
+/* Field definitions for TX buffer descriptors */
+#define ETH_TX_BD_LENGTH_OFFSET 16
+#define ETH_TX_BD_LENGTH_WIDTH 16
+#define ETH_TX_BD_READY_OFFSET 15
+#define ETH_TX_BD_IRQ_OFFSET 14
+#define ETH_TX_BD_WRAP_OFFSET 13
+#define ETH_TX_BD_PAD_OFFSET 12
+#define ETH_TX_BD_CRC_OFFSET 11
+#define ETH_TX_BD_LAST_OFFSET 10
+#define ETH_TX_BD_PAUSE_OFFSET 9
+#define ETH_TX_BD_UNDERRUN_OFFSET 8
+#define ETH_TX_BD_RETRY_OFFSET 4
+#define ETH_TX_BD_RETRY_WIDTH 4
+#define ETH_TX_BD_RETRANSMIT_OFFSET 3
+#define ETH_TX_BD_COLLISION_OFFSET 2
+#define ETH_TX_BD_DEFER_OFFSET 1
+#define ETH_TX_BD_NO_CARRIER_OFFSET 0
+
+
+/* Field definitions for RX buffer descriptors */
+#define ETH_RX_BD_LENGTH_OFFSET 16
+#define ETH_RX_BD_LENGTH_WIDTH 16
+#define ETH_RX_BD_READY_OFFSET 15
+#define ETH_RX_BD_IRQ_OFFSET 14
+#define ETH_RX_BD_WRAP_OFFSET 13
+#define ETH_RX_BD_MISS_OFFSET 7
+#define ETH_RX_BD_UVERRUN_OFFSET 6
+#define ETH_RX_BD_INVALID_OFFSET 5
+#define ETH_RX_BD_DRIBBLE_OFFSET 4
+#define ETH_RX_BD_TOOBIG_OFFSET 3
+#define ETH_RX_BD_TOOSHORT_OFFSET 2
+#define ETH_RX_BD_CRC_OFFSET 1
+#define ETH_RX_BD_COLLISION_OFFSET 0
+
+#endif /* __OR1KSIM_PERIPHERAL_ETHERNET_H */
Index: ps2kbd.h
===================================================================
--- ps2kbd.h (nonexistent)
+++ ps2kbd.h (revision 1765)
@@ -0,0 +1,72 @@
+/* ps2kbd.h -- Very simple PS/2 keyboard simulation header file
+ Copyright (C) 2002 Marko Mlinar, markom@opencores.org
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _PS2KBD_H_
+#define _PS2KBD_H_
+
+/* Device registers */
+#define KBD_CTRL 4
+#define KBD_DATA 0
+#define KBD_SPACE 8
+
+/* Keyboard commands */
+#define KBD_KCMD_RST 0xFF
+#define KBD_KCMD_DK 0xF5
+#define KBD_KCMD_EK 0xF4
+#define KBD_KCMD_ECHO 0xFF
+#define KBD_KCMD_SRL 0xED
+
+/* Keyboard responses */
+#define KBD_KRESP_RSTOK 0xAA
+#define KBD_KRESP_ECHO 0xEE
+#define KBD_KRESP_ACK 0xFA
+
+/* Controller commands */
+#define KBD_CCMD_RCB 0x20
+#define KBD_CCMD_WCB 0x60
+#define KBD_CCMD_ST1 0xAA
+#define KBD_CCMD_ST2 0xAB
+#define KBD_CCMD_DKI 0xAD
+#define KBD_CCMD_EKI 0xAE
+
+/* Status register bits */
+#define KBD_STATUS_OBF 0x01
+#define KBD_STATUS_IBF 0x02
+#define KBD_STATUS_SYS 0x04
+#define KBD_STATUS_A2 0x08
+#define KBD_STATUS_INH 0x10
+#define KBD_STATUS_MOBF 0x20
+#define KBD_STATUS_TO 0x40
+#define KBD_STATUS_PERR 0x80
+
+/* Command byte register bits */
+#define KBD_CCMDBYTE_INT 0x01
+#define KBD_CCMDBYTE_INT2 0x02
+#define KBD_CCMDBYTE_SYS 0x04
+#define KBD_CCMDBYTE_EN 0x10
+#define KBD_CCMDBYTE_EN2 0x20
+#define KBD_CCMDBYTE_XLAT 0x40
+
+/* Length of internal scan code fifo */
+#define KBD_MAX_BUF 0x100
+
+/* Keyboard is checked every KBD_SLOWDOWN cycle */
+#define KBD_BAUD_RATE 1200
+
+#endif /* !_PS2KBD_H_ */
ps2kbd.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: fb.h
===================================================================
--- fb.h (nonexistent)
+++ fb.h (revision 1765)
@@ -0,0 +1,40 @@
+/* fb.h -- Definition of types and structures for simple frame buffer.
+ Copyright (C) 2002 Marko Mlinar, markom@opencores.org
+
+NOTE: device is only partially implemented!
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _FB_H_
+#define _FB_H_
+
+#define FB_SIZEX 640
+#define FB_SIZEY 480
+
+#define CAM_SIZEX 352
+#define CAM_SIZEY 288
+
+/* Relative amount of time spent in refresh */
+#define REFRESH_DIVIDER 20
+
+#define FB_CTRL 0x0000
+#define FB_BUFADDR 0x0004
+#define FB_CAMBUFADDR 0x0008
+#define FB_CAMPOSADDR 0x000c
+#define FB_PAL 0x0400
+
+#endif /* _VGA_H_ */
fb.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: vga.h
===================================================================
--- vga.h (nonexistent)
+++ vga.h (revision 1765)
@@ -0,0 +1,50 @@
+/* vga.h -- Definition of types and structures for Richard's VGA/LCD controler.
+ Copyright (C) 2002 Marko Mlinar, markom@opencores.org
+
+NOTE: device is only partially implemented!
+
+This file is part of OpenRISC 1000 Architectural Simulator.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program 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 General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef _VGA_H_
+#define _VGA_H_
+
+#define VGA_CTRL 0x00 /* Control Register */
+#define VGA_STAT 0x04 /* Status Register */
+#define VGA_HTIM 0x08 /* Horizontal Timing Register */
+#define VGA_VTIM 0x0c /* Vertical Timing Register */
+#define VGA_HVLEN 0x10 /* Horizontal and Vertical Length Register */
+#define VGA_VBARA 0x14 /* Video Memory Base Address Register A */
+#define VGA_VBARB 0x18 /* Video Memory Base Address Register B */
+#define VGA_CLUTA 0x800
+#define VGA_CLUTB 0xc00
+#define VGA_MASK 0xfff
+#define VGA_ADDR_SPACE 1024
+
+
+/* List of implemented registers; all other are ignored. */
+
+/* Control Register */
+#define VGA_CTRL_VEN 0x00000001 /* Video Enable */
+#define VGA_CTRL_CD 0x00000300 /* Color Depth */
+#define VGA_CTRL_PC 0x00000400 /* Pseudo Color */
+
+/* Status Register */
+/* Horiz. Timing Register */
+/* Vert. Timing Register */
+/* Horiz. and Vert. Length Register */
+
+#endif /* _VGA_H_ */
vga.h
Property changes :
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: dma_defs.h
===================================================================
--- dma_defs.h (nonexistent)
+++ dma_defs.h (revision 1765)
@@ -0,0 +1,124 @@
+/* dma_defs.h -- Definition of relative addresses/register bits for DMA
+ Copyright (C) 2001 by Erez Volk, erez@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* Number of channel per DMA controller */
+#define DMA_NUM_CHANNELS 31
+
+
+/* Address space required by one DMA controller */
+#define DMA_ADDR_SPACE 0x400
+
+
+/* Relative Register Addresses */
+#define DMA_CSR 0x00
+#define DMA_INT_MSK_A 0x04
+#define DMA_INT_MSK_B 0x08
+#define DMA_INT_SRC_A 0x0C
+#define DMA_INT_SRC_B 0x10
+
+/* Channel registers definitions */
+#define DMA_CH_BASE 0x20 /* Offset of first channel registers */
+#define DMA_CH_SIZE 0x20 /* Per-channel address space */
+
+/* Per-channel Register Addresses, relative to channel start */
+#define DMA_CH_CSR 0x00
+#define DMA_CH_SZ 0x04
+#define DMA_CH_A0 0x08
+#define DMA_CH_AM0 0x0C
+#define DMA_CH_A1 0x10
+#define DMA_CH_AM1 0x14
+#define DMA_CH_DESC 0x18
+#define DMA_CH_SWPTR 0x1C
+
+/* Field Definitions for the Main CSR */
+#define DMA_CSR_PAUSE_OFFSET 0
+
+/* Field Definitions for the Channel CSR(s) */
+#define DMA_CH_CSR_CH_EN_OFFSET 0
+#define DMA_CH_CSR_DST_SEL_OFFSET 1
+#define DMA_CH_CSR_SRC_SEL_OFFSET 2
+#define DMA_CH_CSR_INC_DST_OFFSET 3
+#define DMA_CH_CSR_INC_SRC_OFFSET 4
+#define DMA_CH_CSR_MODE_OFFSET 5
+#define DMA_CH_CSR_ARS_OFFSET 6
+#define DMA_CH_CSR_USE_ED_OFFSET 7
+#define DMA_CH_CSR_SZ_WB_OFFSET 8
+#define DMA_CH_CSR_STOP_OFFSET 9
+#define DMA_CH_CSR_BUSY_OFFSET 10
+#define DMA_CH_CSR_DONE_OFFSET 11
+#define DMA_CH_CSR_ERR_OFFSET 12
+#define DMA_CH_CSR_PRIORITY_OFFSET 13
+#define DMA_CH_CSR_PRIORITY_WIDTH 3
+#define DMA_CH_CSR_REST_EN_OFFSET 16
+#define DMA_CH_CSR_INE_ERR_OFFSET 17
+#define DMA_CH_CSR_INE_DONE_OFFSET 18
+#define DMA_CH_CSR_INE_CHK_DONE_OFFSET 19
+#define DMA_CH_CSR_INT_ERR_OFFSET 20
+#define DMA_CH_CSR_INT_DONE_OFFSET 21
+#define DMA_CH_CSR_INT_CHUNK_DONE_OFFSET 22
+#define DMA_CH_CSR_RESERVED_OFFSET 23
+#define DMA_CH_CSR_RESERVED_WIDTH 9
+
+/* Masks -- Writable and readonly parts of the register */
+#define DMA_CH_CSR_WRITE_MASK 0x000FE3FF
+
+/* Field definitions for Channel Size Registers */
+#define DMA_CH_SZ_TOT_SZ_OFFSET 0
+#define DMA_CH_SZ_TOT_SZ_WIDTH 12
+#define DMA_CH_SZ_CHK_SZ_OFFSET 16
+#define DMA_CH_SZ_CHK_SZ_WIDTH 9
+
+/* Field definitions for Channel Address Registers CHn_Am */
+#define DMA_CH_A0_ADDR_OFFSET 2
+#define DMA_CH_A0_ADDR_WIDTH 30
+#define DMA_CH_A1_ADDR_OFFSET 2
+#define DMA_CH_A1_ADDR_WIDTH 30
+
+/* Field definitions for Channel Address Mask Registers CHn_AMm */
+#define DMA_CH_AM0_MASK_OFFSET 4
+#define DMA_CH_AM0_MASK_WIDTH 28
+#define DMA_CH_AM1_MASK_OFFSET 4
+#define DMA_CH_AM1_MASK_WIDTH 28
+
+/* Field definitions for Channel Linked List descriptor Pointer CHn_DESC */
+#define DMA_CH_DESC_ADDR_OFFSET 2
+#define DMA_CH_DESC_ADDR_WIDTH 30
+
+/* Field definitions for Channel Software Pointer */
+#define DMA_CH_SWPTR_PTR_OFFSET 2
+#define DMA_CH_SWPTR_PTR_WIDTH 29
+#define DMA_CH_SWPTR_EN_OFFSET 31
+
+
+/* Structure of linked list descriptors (offsets of elements) */
+#define DMA_DESC_CSR 0x00
+#define DMA_DESC_ADR0 0x04
+#define DMA_DESC_ADR1 0x08
+#define DMA_DESC_NEXT 0x0C
+
+/* Field definitions for linked list descriptor DESC_CSR */
+#define DMA_DESC_CSR_EOL_OFFSET 20
+#define DMA_DESC_CSR_INC_SRC_OFFSET 19
+#define DMA_DESC_CSR_INC_DST_OFFSET 18
+#define DMA_DESC_CSR_SRC_SEL_OFFSET 17
+#define DMA_DESC_CSR_DST_SEL_OFFSET 16
+#define DMA_DESC_CSR_TOT_SZ_OFFSET 0
+#define DMA_DESC_CSR_TOT_SZ_WIDTH 12
+
Index: atadevice_cmdi.h
===================================================================
--- atadevice_cmdi.h (nonexistent)
+++ atadevice_cmdi.h (revision 1765)
@@ -0,0 +1,119 @@
+/*
+ atadevice_cmdi.h -- ATA Device command interpreter
+ Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+
+/**********************************************************************/
+/* define FIRMWARE revision; current revision of OR1Ksim ATA code. */
+/* coded using the release date (yyyymmdd, but shuffled) */
+#define FIRMWARE "02207031"
+
+
+/**********************************************************************/
+/* Define default CHS translation parameters */
+/* bytes per sector */
+#define BYTES_PER_SECTOR 512
+
+/* number of default heads ( -1) */
+#define HEADS 7
+
+/* number of default sectors per track */
+#define SECTORS 32
+
+
+/**********************************************************************/
+/* Define supported DMA and PIO modes */
+/* define the highest Multiword DMA mode; 2, 1, 0, -1(no DMA) */
+#define MWDMA 2
+
+/* define the highest supported PIO mode; 4, 3, 2, 1, 0(obsolete) */
+#define PIO 4
+
+
+/**********************************************************************/
+/* Define DMA and PIO cycle times */
+/* define the minimum Multiword DMA cycle time per word (in nsec) */
+#define MIN_MWDMA_CYCLE_TIME 100
+
+/* define the manufacturer's recommended Multiword DMA cycle time */
+#define RECOMMENDED_MWDMA_CYCLE_TIME 100
+
+/* define the minimum PIO cycle time per word (in nsec), no IORDY */
+#define MIN_PIO_CYCLE_TIME_NO_IORDY 100
+
+/* define the minimum PIO cycle time per word (in nsec), with IORDY */
+#define MIN_PIO_CYCLE_TIME_IORDY 100
+
+
+/**********************************************************************/
+/* Define supported command sets */
+/* 1=command is supported */
+/* 0=command is not (yet) supported */
+#define SUPPORT_NOP_CMD 0
+#define SUPPORT_READ_BUFFER_CMD 0
+#define SUPPORT_WRITE_BUFFER_CMD 0
+#define SUPPORT_HOST_PROTECTED_AREA 0
+#define SUPPORT_DEVICE_RESET_CMD 1
+#define SUPPORT_SERVICE_INTERRUPT 0
+#define SUPPORT_RELEASE_INTERRUPT 0
+#define SUPPORT_LOOKAHEAD 0
+#define SUPPORT_WRITE_CACHE 0
+#define SUPPORT_POWER_MANAGEMENT 0
+#define SUPPORT_REMOVABLE_MEDIA 0
+#define SUPPORT_SECURITY_MODE 0
+#define SUPPORT_SMART 0
+#define SUPPORT_SET_MAX 0
+#define SET_FEATURES_REQUIRED_AFTER_POWER_UP 0
+#define SUPPORT_POWER_UP_IN_STANDBY_MODE 0
+#define SUPPORT_REMOVABLE_MEDIA_NOTIFICATION 0
+#define SUPPORT_APM 0
+#define SUPPORT_CFA 0
+#define SUPPORT_READ_WRITE_DMA_QUEUED 0
+#define SUPPORT_DOWNLOAD_MICROCODE 0
+
+/*
+Queue depth defines the maximum queue depth supported by the device.
+This includes all commands for which the command acceptance has occured
+and command completion has not occured. This value is used for the DMA
+READ/WRITE QUEUE command.
+
+QUEUE_DEPTH = actual_queue_depth -1
+*/
+#define QUEUE_DEPTH 0
+
+
+
+/**********************************************************************/
+/* Internal defines */
+#define PACKET_SIGNATURE 1
+
+
+/*
+ ----------------
+ -- Prototypes --
+ ----------------
+*/
+int ata_device_execute_cmd(ata_device *device);
+
+void ata_device_reset_cmd(ata_device *device);
+void ata_execute_device_diagnostics_cmd(ata_device *device);
+void ata_identify_device_cmd(ata_device *device);
+void ata_initialize_device_parameters_cmd(ata_device *device);
+void ata_read_sectors_cmd(ata_device *device);
Index: atacmd.h
===================================================================
--- atacmd.h (nonexistent)
+++ atacmd.h (revision 1765)
@@ -0,0 +1,128 @@
+/*
+ atacommon.h -- ATA Host code simulation
+ Common defines for ATA Host and ATA Device
+ Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ * Definitions for the Opencores ATA Controller Core
+ */
+
+#ifndef __OR1KSIM_ATACMD_H
+#define __OR1KSIM_ATACMD_H
+
+/* ---------------------------- */
+/* ----- ATA commands ----- */
+/* ---------------------------- */
+#define CFA_ERASE_SECTORS 0xC0
+#define CFA_REQUEST_EXTENDED_ERROR_CODE 0x03
+#define CFA_TRANSLATE_SECTOR 0x87
+#define CFA_WRITE_MULTIPLE_WITHOUT_ERASE 0xCD
+#define CFA_WRITE_SECTORS_WITHOUT_ERASE 0x38
+#define CHECK_POWER_MODE 0xE5
+#define DEVICE_RESET 0x08
+#define DOWNLOAD_MICROCODE 0x92
+#define EXECUTE_DEVICE_DIAGNOSTICS 0x90
+#define FLUSH_CACHE 0xE7
+#define GET_MEDIA_STATUS 0xDA
+#define IDENTIFY_DEVICE 0xEC
+#define IDENTIFY_PACKET_DEVICE 0xA1
+#define IDLE 0xE3
+#define IDLE_IMMEDIATE 0xE1
+#define INITIALIZE_DEVICE_PARAMETERS 0x91
+#define MEDIA_EJECT 0xED
+#define MEDIA_LOCK 0xDE
+#define MEDIA_UNLOCK 0xDF
+#define NOP 0x00
+#define PACKET 0xA0
+#define READ_BUFFER 0xE4
+#define READ_DMA 0xC8
+#define READ_DMA_QUEUED 0xC7
+#define READ_MULTIPLE 0xC4
+#define READ_NATIVE_MAX_ADDRESS 0xF8
+#define READ_SECTOR 0x20
+#define READ_SECTORS 0x20
+#define READ_VERIFY_SECTOR 0x40
+#define READ_VERIFY_SECTORS 0x40
+#define SECURITY_DISABLE_PASSWORD 0xF6
+#define SECURITY_ERASE_PREPARE 0xF3
+#define SECURITY_ERASE_UNIT 0xF4
+#define SECURITY_FREEZE_LOCK 0xF5
+#define SECURITY_SET_PASSWORD 0xF1
+#define SECURITY_UNLOCK 0xF2
+#define SEEK 0x70
+#define SERVICE 0xA2
+#define SET_FEATURES 0xEF
+#define SET_MAX 0xF9
+#define SET_MULTIPLE_MODE 0xC6
+#define SLEEP 0xE6
+#define SMART 0xB0
+#define STANDBY 0xE2
+#define STANDBY_IMMEDIATE 0xE0
+#define WRITE_BUFFER 0xE8
+#define WRITE_DMA 0xCA
+#define WRITE_DMA_QUEUED 0xCC
+#define WRITE_MULTIPLE 0xC5
+#define WRITE_SECTOR 0x30
+#define WRITE_SECTORS 0x30
+
+
+/* SET_FEATURES has a number of sub-commands (in Features Register) */
+#define CFA_ENABLE_8BIT_PIO_TRANSFER_MODE 0x01
+#define ENABLE_WRITE_CACHE 0x02
+#define SET_TRANSFER_MODE_SECTOR_COUNT_REG 0x03
+#define ENABLE_ADVANCED_POWER_MANAGEMENT 0x05
+#define ENABLE_POWERUP_IN_STANDBY_FEATURE_SET 0x06
+#define POWERUP_IN_STANDBY_FEATURE_SET_SPINUP 0x07
+#define CFA_ENABLE_POWER_MODE1 0x0A
+#define DISABLE_MEDIA_STATUS_NOTIFICATION 0x31
+#define DISABLE_READ_LOOKAHEAD 0x55
+#define ENABLE_RELEASE_INTERRUPT 0x5D
+#define ENABLE_SERVICE_INTERRUPT 0x5E
+#define DISABLE_REVERTING_TO_POWERON_DEFAULTS 0x66
+#define CFA_DISABLE_8BIT_PIO_TRANSFER_MODE 0x81
+#define DISABLE_WRITE_CACHE 0x82
+#define DISABLE_ADVANCED_POWER_MANAGEMENT 0x85
+#define DISABLE_POWERUP_IN_STANDBY_FEATURE_SET 0x86
+#define CFA_DISABLE_POWER_MODE1 0x8A
+#define ENABLE_MEDIA_STATUS_NOTIFICATION 0x95
+#define ENABLE_READ_LOOKAHEAD_FEATURE 0xAA
+#define ENABLE_REVERTING_TO_POWERON_DEFAULTS 0xCC
+#define DISABLE_RELEASE_INTERRUPT 0xDD
+#define DISABLE_SERVICE_INTERRUPT 0xDE
+
+/* SET_MAX has a number of sub-commands (in Features Register) */
+#define SET_MAX_ADDRESS 0x00
+#define SET_MAX_SET_PASSWORD 0x01
+#define SET_MAX_LOCK 0x02
+#define SET_MAX_UNLOCK 0x03
+#define SET_MAX_FREEZE_LOCK 0x04
+
+/* SET_MAX has a number of sub-commands (in Features Register) */
+#define SMART_READ_DATA 0xD0
+#define SMART_ATTRIBITE_AUTOSAVE 0xD1
+#define SMART_SAVE_ATTRIBUTE_VALUES 0xD3
+#define SMART_EXECUTE_OFFLINE_IMMEDIATE 0xD4
+#define SMART_READ_LOG 0xD5
+#define SMART_WRITE_LOG 0xD6
+#define SMART_ENABLE_OPERATIONS 0xD8
+#define SMART_DISABLE_OPERATIONS 0xD9
+#define SMART_RETURN_STATUS 0xDA
+
+#endif
Index: atahost_define.h
===================================================================
--- atahost_define.h (nonexistent)
+++ atahost_define.h (revision 1765)
@@ -0,0 +1,47 @@
+/*
+ atahost.h -- ATA Host code simulation
+ Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+ * User configuration of the OCIDEC ata core
+ */
+
+#ifndef __OR1KSIM_ATAC_H
+#define __OR1KSIM_ATAC_H
+
+
+/* define core (OCIDEC) type */
+#define DEV_ID 1
+
+/* define core version */
+#define REV 0
+
+/* define timing reset values */
+#define PIO_MODE0_T1 6
+#define PIO_MODE0_T2 28
+#define PIO_MODE0_T4 2
+#define PIO_MODE0_TEOC 23
+
+#define DMA_MODE0_TM 4
+#define DMA_MODE0_TD 21
+#define DMA_MODE0_TEOC 21
+
+
+#endif
Index: fields.h
===================================================================
--- fields.h (nonexistent)
+++ fields.h (revision 1765)
@@ -0,0 +1,59 @@
+/* fields.h -- Some macros to help with bit field definitions
+ Copyright (C) 2001 by Erez Volk, erez@opencores.org
+
+ This file is part of OpenRISC 1000 Architectural Simulator.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef __FIELDS_H
+#define __FIELDS_H
+
+
+/* Macros to get/set a field in a register
+ * Example:
+ * unsigned long done, priority, channel_csr;
+ *
+ * priority = GET_FIELD( channel_csr, DMA_CH_CSR, PRIORITY );
+ * SET_FIELD( channel_csr, DMA_CH_CSR, PRIORITY, priority );
+ *
+ * done = TEST_FLAG( channel_csr, DMA_CH_CSR, DONE );
+ * SET_FLAG( channel_csr, DMA_CH_CSR, DONE );
+ * CLEAR_FLAG( channel_csr, DMA_CH_CSR, DONE );
+ * ASSIGN_FLAG( channel_csr, DMA_CH_CSR, done );
+ *
+ * For each field, we then define e.g.
+ * #define DMA_CH_CSR_PRIORITY_OFFSET 13
+ * #define DMA_CH_CSR_PRIORITY_WIDTH 3 // not needed for flags, which always have width = 1
+ */
+
+#define FLAG_SHIFT(reg_name,flag_name) (reg_name##_##flag_name##_OFFSET)
+#define FLAG_MASK(reg_name,flag_name) (1LU << reg_name##_##flag_name##_OFFSET)
+
+#define TEST_FLAG(reg_value,reg_name,flag_name) (((reg_value ) >> reg_name##_##flag_name##_OFFSET) & 1LU)
+#define SET_FLAG(reg_value,reg_name,flag_name) { (reg_value) |= 1LU << reg_name##_##flag_name##_OFFSET; }
+#define CLEAR_FLAG(reg_value,reg_name,flag_name) { (reg_value) &= ~(1LU << reg_name##_##flag_name##_OFFSET); }
+#define ASSIGN_FLAG(reg_value,reg_name,flag_name,flag_value) { \
+ (reg_value) = flag_value ? ((reg_value) | (1LU << reg_name##_##flag_name##_OFFSET)) : ((reg_value) & ~(1LU << reg_name##_##flag_name##_OFFSET)); }
+
+#define FIELD_SHIFT(reg_name,field_name) (reg_name##_##field_name##_OFFSET)
+#define FIELD_MASK(reg_name,field_name) ((~(~0LU << reg_name##_##field_name##_WIDTH)) << reg_name##_##field_name##_OFFSET)
+
+#define GET_FIELD(reg_value,reg_name,field_name) (((reg_value) >> reg_name##_##field_name##_OFFSET) & (~(~0LU << reg_name##_##field_name##_WIDTH)))
+#define SET_FIELD(reg_value,reg_name,field_name,field_value) { \
+ (reg_value) = ((reg_value) & ~((~(~0LU << reg_name##_##field_name##_WIDTH)) << reg_name##_##field_name##_OFFSET)) | ((field_value) << reg_name##_##field_name##_OFFSET); }
+
+#endif /* __FIELDS_H */
Index: crc32.c
===================================================================
--- crc32.c (nonexistent)
+++ crc32.c (revision 1765)
@@ -0,0 +1,67 @@
+#include "crc32.h"
+
+static unsigned long crc32_table[256] =
+{
+ 0x00000000L, 0x77073096L, 0xEE0E612CL, 0x990951BAL, 0x076DC419L, 0x706AF48FL, 0xE963A535L, 0x9E6495A3L,
+ 0x0EDB8832L, 0x79DCB8A4L, 0xE0D5E91EL, 0x97D2D988L, 0x09B64C2BL, 0x7EB17CBDL, 0xE7B82D07L, 0x90BF1D91L,
+ 0x1DB71064L, 0x6AB020F2L, 0xF3B97148L, 0x84BE41DEL, 0x1ADAD47DL, 0x6DDDE4EBL, 0xF4D4B551L, 0x83D385C7L,
+ 0x136C9856L, 0x646BA8C0L, 0xFD62F97AL, 0x8A65C9ECL, 0x14015C4FL, 0x63066CD9L, 0xFA0F3D63L, 0x8D080DF5L,
+ 0x3B6E20C8L, 0x4C69105EL, 0xD56041E4L, 0xA2677172L, 0x3C03E4D1L, 0x4B04D447L, 0xD20D85FDL, 0xA50AB56BL,
+ 0x35B5A8FAL, 0x42B2986CL, 0xDBBBC9D6L, 0xACBCF940L, 0x32D86CE3L, 0x45DF5C75L, 0xDCD60DCFL, 0xABD13D59L,
+ 0x26D930ACL, 0x51DE003AL, 0xC8D75180L, 0xBFD06116L, 0x21B4F4B5L, 0x56B3C423L, 0xCFBA9599L, 0xB8BDA50FL,
+ 0x2802B89EL, 0x5F058808L, 0xC60CD9B2L, 0xB10BE924L, 0x2F6F7C87L, 0x58684C11L, 0xC1611DABL, 0xB6662D3DL,
+ 0x76DC4190L, 0x01DB7106L, 0x98D220BCL, 0xEFD5102AL, 0x71B18589L, 0x06B6B51FL, 0x9FBFE4A5L, 0xE8B8D433L,
+ 0x7807C9A2L, 0x0F00F934L, 0x9609A88EL, 0xE10E9818L, 0x7F6A0DBBL, 0x086D3D2DL, 0x91646C97L, 0xE6635C01L,
+ 0x6B6B51F4L, 0x1C6C6162L, 0x856530D8L, 0xF262004EL, 0x6C0695EDL, 0x1B01A57BL, 0x8208F4C1L, 0xF50FC457L,
+ 0x65B0D9C6L, 0x12B7E950L, 0x8BBEB8EAL, 0xFCB9887CL, 0x62DD1DDFL, 0x15DA2D49L, 0x8CD37CF3L, 0xFBD44C65L,
+ 0x4DB26158L, 0x3AB551CEL, 0xA3BC0074L, 0xD4BB30E2L, 0x4ADFA541L, 0x3DD895D7L, 0xA4D1C46DL, 0xD3D6F4FBL,
+ 0x4369E96AL, 0x346ED9FCL, 0xAD678846L, 0xDA60B8D0L, 0x44042D73L, 0x33031DE5L, 0xAA0A4C5FL, 0xDD0D7CC9L,
+ 0x5005713CL, 0x270241AAL, 0xBE0B1010L, 0xC90C2086L, 0x5768B525L, 0x206F85B3L, 0xB966D409L, 0xCE61E49FL,
+ 0x5EDEF90EL, 0x29D9C998L, 0xB0D09822L, 0xC7D7A8B4L, 0x59B33D17L, 0x2EB40D81L, 0xB7BD5C3BL, 0xC0BA6CADL,
+ 0xEDB88320L, 0x9ABFB3B6L, 0x03B6E20CL, 0x74B1D29AL, 0xEAD54739L, 0x9DD277AFL, 0x04DB2615L, 0x73DC1683L,
+ 0xE3630B12L, 0x94643B84L, 0x0D6D6A3EL, 0x7A6A5AA8L, 0xE40ECF0BL, 0x9309FF9DL, 0x0A00AE27L, 0x7D079EB1L,
+ 0xF00F9344L, 0x8708A3D2L, 0x1E01F268L, 0x6906C2FEL, 0xF762575DL, 0x806567CBL, 0x196C3671L, 0x6E6B06E7L,
+ 0xFED41B76L, 0x89D32BE0L, 0x10DA7A5AL, 0x67DD4ACCL, 0xF9B9DF6FL, 0x8EBEEFF9L, 0x17B7BE43L, 0x60B08ED5L,
+ 0xD6D6A3E8L, 0xA1D1937EL, 0x38D8C2C4L, 0x4FDFF252L, 0xD1BB67F1L, 0xA6BC5767L, 0x3FB506DDL, 0x48B2364BL,
+ 0xD80D2BDAL, 0xAF0A1B4CL, 0x36034AF6L, 0x41047A60L, 0xDF60EFC3L, 0xA867DF55L, 0x316E8EEFL, 0x4669BE79L,
+ 0xCB61B38CL, 0xBC66831AL, 0x256FD2A0L, 0x5268E236L, 0xCC0C7795L, 0xBB0B4703L, 0x220216B9L, 0x5505262FL,
+ 0xC5BA3BBEL, 0xB2BD0B28L, 0x2BB45A92L, 0x5CB36A04L, 0xC2D7FFA7L, 0xB5D0CF31L, 0x2CD99E8BL, 0x5BDEAE1DL,
+ 0x9B64C2B0L, 0xEC63F226L, 0x756AA39CL, 0x026D930AL, 0x9C0906A9L, 0xEB0E363FL, 0x72076785L, 0x05005713L,
+ 0x95BF4A82L, 0xE2B87A14L, 0x7BB12BAEL, 0x0CB61B38L, 0x92D28E9BL, 0xE5D5BE0DL, 0x7CDCEFB7L, 0x0BDBDF21L,
+ 0x86D3D2D4L, 0xF1D4E242L, 0x68DDB3F8L, 0x1FDA836EL, 0x81BE16CDL, 0xF6B9265BL, 0x6FB077E1L, 0x18B74777L,
+ 0x88085AE6L, 0xFF0F6A70L, 0x66063BCAL, 0x11010B5CL, 0x8F659EFFL, 0xF862AE69L, 0x616BFFD3L, 0x166CCF45L,
+ 0xA00AE278L, 0xD70DD2EEL, 0x4E048354L, 0x3903B3C2L, 0xA7672661L, 0xD06016F7L, 0x4969474DL, 0x3E6E77DBL,
+ 0xAED16A4AL, 0xD9D65ADCL, 0x40DF0B66L, 0x37D83BF0L, 0xA9BCAE53L, 0xDEBB9EC5L, 0x47B2CF7FL, 0x30B5FFE9L,
+ 0xBDBDF21CL, 0xCABAC28AL, 0x53B39330L, 0x24B4A3A6L, 0xBAD03605L, 0xCDD70693L, 0x54DE5729L, 0x23D967BFL,
+ 0xB3667A2EL, 0xC4614AB8L, 0x5D681B02L, 0x2A6F2B94L, 0xB40BBE37L, 0xC30C8EA1L, 0x5A05DF1BL, 0x2D02EF8DL
+};
+
+
+unsigned long crc32( const void *buf, unsigned len )
+{
+ unsigned long crc;
+
+ crc32_init( &crc );
+ crc32_feed_bytes( &crc, buf, len );
+ crc32_close( &crc );
+ return crc;
+}
+
+
+void crc32_init( unsigned long *value )
+{
+ *value = 0xFFFFFFFF;
+}
+
+void crc32_feed_bytes( unsigned long *value, const void *buf, unsigned len )
+{
+ const unsigned char *p;
+
+ for ( p = (const unsigned char *)buf; len > 0; ++ p, -- len )
+ *value = (*value >> 8) ^ crc32_table[(*value ^ *p) & 0xFF];
+}
+
+void crc32_close( unsigned long *value )
+{
+ *value = ~*value;
+}
Index: crc32.h
===================================================================
--- crc32.h (nonexistent)
+++ crc32.h (revision 1765)
@@ -0,0 +1,13 @@
+#ifndef __CRC32_H
+#define __CRC32_H
+
+
+/* Calculate CRC of buffer in one go */
+unsigned long crc32( const void *buf, unsigned len );
+
+/* Calculate incrementally */
+void crc32_init( unsigned long *value );
+void crc32_feed_bytes( unsigned long *value, const void *buf, unsigned len );
+void crc32_close( unsigned long *value );
+
+#endif /* ___CRC32_H */
Index: .
===================================================================
--- . (nonexistent)
+++ . (revision 1765)
.
Property changes :
Added: svn:ignore
## -0,0 +1,2 ##
+Makefile
+.deps