OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /or1k/tags/nog_patch_40/or1ksim/peripheral
    from Rev 1405 to Rev 1765
    Reverse comparison

Rev 1405 → Rev 1765

/dma.c
0,0 → 1,538
/* 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 <string.h>
 
#include "config.h"
 
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#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"
 
/* 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 i, j;
struct dma_controller *dma = dat;
 
if ( dma->baseaddr == 0 )
return;
 
PRINTF( "\nDMA controller %u at 0x%"PRIxADDR":\n", i, 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;
 
addr -= dma->baseaddr;
 
if ( addr % 4 != 0 ) {
fprintf( stderr, "dma_read32( 0x%"PRIxADDR" ): Not register-aligned\n",
addr + dma->baseaddr );
runtime.sim.cont_run = 0;
return 0;
}
 
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 );
runtime.sim.cont_run = 0;
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;
 
addr -= dma->baseaddr;
 
if ( addr % 4 != 0 ) {
fprintf( stderr, "dma_write32( 0x%"PRIxADDR", 0x%08"PRIx32" ): Not register-aligned\n", addr + dma->baseaddr, value );
runtime.sim.cont_run = 0;
return;
}
 
/* 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 );
runtime.sim.cont_run = 0;
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 )
{
int breakpoint = 0;
struct dma_channel *channel = dat;
/* Do we need to abort? */
if ( TEST_FLAG( channel->regs.csr, DMA_CH_CSR, STOP ) ) {
debug( 3, "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 ) ) {
debug( 4, "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 ) ) {
debug( 3, "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,
&breakpoint, 0, 0 ),
&breakpoint, 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 ) ) {
debug( 3, "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 )
{
int breakpoint = 0;
unsigned long desc_csr = eval_direct32( channel->regs.desc + DMA_DESC_CSR, &breakpoint, 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, &breakpoint, 0, 0 );
channel->regs.a1 = eval_direct32( channel->regs.desc + DMA_DESC_ADR1, &breakpoint, 0, 0 );
channel->current_descriptor = channel->regs.desc;
channel->regs.desc = eval_direct32( channel->regs.desc + DMA_DESC_NEXT, &breakpoint, 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 )
{
debug( 4, "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_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;
 
return new;
}
 
void dma_sec_end(void *dat)
{
struct dma_controller *dma = dat;
struct dma_controller *cur;
 
register_memoryarea( dma->baseaddr, DMA_ADDR_SPACE, 4, 0, dma_read32, dma_write32, dat );
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, "baseaddr", paramt_addr, dma_baseaddr);
reg_config_param(sec, "vapi_id", paramt_addr, dma_vapi_id);
}
/16450.c
0,0 → 1,776
/* 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 and modem control lines changes (the
only DCE responses are incoming characters from the file stream).
*/
 
#include <stdlib.h>
#include <stdio.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 "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))
 
/* Number of clock cycles (one clock cycle is one call to the uart_clock())
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;
}
 
/* Set a specific UART register with value. */
void uart_write_byte(oraddr_t addr, uint32_t value, void *dat)
{
struct dev_16450 *uart = dat;
TRACE("uart_write_byte(%"PRIxADDR",%02"PRIx32")\n", addr, value);
 
if (uart->regs.lcr & UART_LCR_DLAB) {
switch (addr % UART_ADDR_SPACE) {
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:
uart->regs.dlh = value;
return;
}
}
switch (addr % UART_ADDR_SPACE) {
case UART_TXBUF:
if (uart->istat.txbuf_full < uart->fifo_len) {
uart->istat.txbuf_full++;
uart->regs.txbuf[uart->istat.txbuf_head] = value;
uart->istat.txbuf_head = (uart->istat.txbuf_head + 1) % uart->fifo_len;
} else
uart->regs.txbuf[uart->istat.txbuf_head] = value;
 
uart->regs.lsr &= ~(UART_LSR_TXSERE | UART_LSR_TXBUFE);
if (uart->regs.iir & UART_IIR_THRI)
uart->istat.thre_int = 0;
break;
case UART_FCR:
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
uart->istat.thre_int = (uart->fifo_len == 16);
}
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;
}
break;
case UART_IER:
uart->regs.ier = value & UART_VALID_IER;
break;
case UART_LCR:
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:
uart->regs.mcr = value & UART_VALID_MCR;
break;
case UART_SCR:
uart->regs.scr = value;
break;
default:
TRACE("write out of range (addr %x)\n", addr);
}
}
 
/* Read a specific UART register. */
uint32_t uart_read_byte(oraddr_t addr, void *dat)
{
struct dev_16450 *uart = dat;
uint8_t value = 0;
TRACE("uart_read_byte(%"PRIxADDR")", addr);
if (uart->regs.lcr & UART_LCR_DLAB) {
switch (addr % UART_ADDR_SPACE) {
case UART_DLL:
value = uart->regs.dll;
TRACE("= %"PRIx8"\n", value);
return value;
case UART_DLH:
value = uart->regs.dlh;
TRACE("= %"PRIx8"\n", value);
return value;
}
}
switch (addr % UART_ADDR_SPACE) {
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(")");
}
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--;
}
if (uart->istat.rxbuf_full)
uart->regs.lsr |= UART_LSR_RDRDY;
else
uart->regs.lsr &= ~UART_LSR_RDRDY;
uart->istat.timeout_count = 0;
break;
case UART_IER:
value = uart->regs.ier & UART_VALID_IER;
break;
case UART_IIR:
value = (uart->regs.iir & UART_VALID_IIR) | 0xc0;
if (uart->regs.iir & UART_IIR_THRI)
uart->istat.thre_int = 0;
break;
case UART_LCR:
value = uart->regs.lcr & UART_VALID_LCR;
break;
case UART_MCR:
value = 0;
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);
break;
case UART_MSR:
value = uart->regs.msr & UART_VALID_MSR;
uart->regs.msr = 0;
break;
case UART_SCR:
value = uart->regs.scr;
break;
default:
TRACE("read out of range (addr %"PRIxADDR")\n", addr);
}
TRACE(" = %"PRIx8"\n", value);
return value;
}
 
/* 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);
}
}
 
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);
PRINTF ("vapi_send (%08lx, %08x)\n", uart->vapi_id, data);
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);
}
}
uart->istat.txser_full = 0;
uart->istat.txser_clks = 0;
}
 
/* Adds a character to the FIFO */
 
void uart_add_char (struct dev_16450 *uart, int ch)
{
if (uart->istat.rxbuf_full + 1 > uart->fifo_len)
uart->regs.lsr |= UART_LSR_OVRRUN | UART_LSR_RXERR;
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;
uart->istat.rxbuf_full++;
}
uart->regs.lsr |= UART_LSR_RDRDY;
uart->istat.timeout_count = 0;
}
 
/* Simulation hook. Must be called every clock cycle to simulate all UART
devices. It does internal functional UART simulation. */
void uart_clock16 (void *dat)
{
struct dev_16450 *uart = dat;
int retval;
 
/* Schedule for later */
SCHED_ADD (uart_clock16, dat, UART_CLOCK_DIVIDER);
 
TRACE("Running uart clock:\n");
/* If VAPI is not selected, UART communicates with two file streams;
if VAPI is selected, we use VAPI streams. */
/* if txfs is corrupted, skip this uart. */
if (!uart->vapi_id && !channel_ok(uart->channel)) return;
 
TRACE("\tChannel stream or VAPI checks out ok\n");
if (uart->vapi.next_break_cnt >= 0)
if (--uart->vapi.next_break_cnt < 0) {
if (!(uart->vapi.cur_break = uart->vapi.next_break))
uart->istat.break_set = 0;
}
 
/***************** Transmit *****************/
TRACE("\tuart->istat.txser_full = %i\n", uart->istat.txser_full);
TRACE("\tuart->istat.txbuf_full = %i\n", uart->istat.txser_full);
TRACE("\tuart->char_clks = %li\n", uart->char_clks);
if (!uart->istat.txser_full) {
// uart->regs.lsr |= UART_LSR_TXBUFE;
if (uart->istat.txbuf_full) {
uart->iregs.txser = uart->regs.txbuf[uart->istat.txbuf_tail];
uart->istat.txbuf_tail = (uart->istat.txbuf_tail + 1) % uart->fifo_len;
uart->istat.txser_full = 1;
uart->istat.txbuf_full--;
uart->regs.lsr &= ~UART_LSR_TXSERE;
 
// 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->istat.thre_int = 1;
uart->regs.lsr |= UART_LSR_TXBUFE;
}
} else {
uart->regs.lsr |= UART_LSR_TXSERE;
}
} else if (uart->char_clks <= uart->istat.txser_clks++) {
send_char(uart, (uart->regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
} else {
/* We are still sending char here*/
/* Check if we set the break bit */
if (uart->regs.lcr & UART_LCR_SBC) {
if (!uart->vapi.break_sent) {
#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);
uart->vapi.break_sent = 1;
}
/* mark as character was sent */
uart->istat.txser_full = 0;
uart->istat.txser_clks = 0;
} else
uart->vapi.break_sent = 0;
 
}
/***************** Receive *****************/
/* Is there a break? */
if (uart->vapi.cur_break) {
uart->vapi.cur_break_cnt++;
if (uart->vapi.cur_break_cnt > UART_BREAK_COUNT * uart->vapi.char_clks) {
if (!uart->istat.break_set) {
unsigned lsr;
uart->istat.break_set = 1;
lsr = UART_LSR_BREAK | UART_LSR_RXERR | UART_LSR_RDRDY;
PRINTF ("[%x]\n", uart->regs.lsr);
uart->istat.rxser_full = 0;
uart->istat.rxser_clks = 0;
uart_add_char (uart, lsr << 8);
} else
uart->vapi.cur_break_cnt = 0;
}
if (uart->istat.rxser_full) {
uart->istat.rxser_full = 0;
uart->istat.rxser_clks = 0;
}
} else {
if (uart->istat.rxser_full) {
if (uart->char_clks <= uart->istat.rxser_clks++) {
/* Set unused character bits to zero and allow lsr register in fifo */
uart->iregs.rxser &= ((1 << ((uart->regs.lcr & 3) + 5)) - 1) | 0xff00;
TRACE("\tReceiving 0x%02lx'%c' via UART (at %"PRIxADDR"...\n",
uart->iregs.rxser, (char)uart->iregs.rxser, uart->baseaddr);
PRINTF ("%c", (char)uart->iregs.rxser);
uart->istat.rxser_full = 0;
uart->istat.rxser_clks = 0;
uart_add_char (uart, uart->iregs.rxser);
}
}
}
 
/* Check if there is something waiting, and put it into rxser */
if (uart->regs.mcr & UART_MCR_LOOP) {
uart->iregs.rxser = uart->iregs.loopback;
uart->istat.rxser_full = 1;
} else {
if (!uart->vapi_id) {
if(uart->istat.rxser_full == 0) {
if (uart->slowdown)
uart->slowdown--;
else {
char buffer[1];
retval = channel_read(uart->channel, buffer, 1);
if(retval < 0)
perror(uart->channel_str);
else if(retval > 0) {
uart->iregs.rxser = (unsigned char)buffer[0];
uart->istat.rxser_full = 1;
} else
uart->slowdown = UART_FGETC_SLOWDOWN;
}
}
} else { /* VAPI */
int received = 0;
/* do not handle commands while receiving */
if (uart->istat.rxser_full) return;
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) {
WARN("WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n",
uart->vapi.lcr & ~UART_LCR_SBC, uart->regs.lcr & ~UART_LCR_SBC);
/* 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;
}
uart->istat.rxser_full = 1;
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:
uart->vapi.next_break_cnt = data & 0xffff;
uart->vapi.next_break = (data >> 16) & 1;
break;
default:
WARN ("WARNING: Invalid vapi command %02lx\n", data >> 24);
break;
}
} else break;
}
}
}
/***************** Loopback *****************/
if (uart->regs.mcr & UART_MCR_LOOP) {
TRACE("uart_clock: Loopback\n");
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.lsr & UART_LSR_RDRDY)
uart->istat.timeout_count++;
/* Update LSR error bits from the ones from rx FIFO */
if (uart->istat.rxbuf_full) {
uart->regs.lsr |= uart->regs.rxbuf[uart->istat.rxbuf_tail] >> 8;
/* we must delete the lsr status, so that we can clear it from lsr */
uart->regs.rxbuf[uart->istat.rxbuf_tail] &= 0xff;
}
/* Interrupt detection in proper priority order. */
uart->regs.iir = UART_IIR_NO_INT;
if (uart->regs.ier & UART_IER_RLSI && /* Receiver LS */
uart->regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
| UART_LSR_FRAME | UART_LSR_BREAK)) {
uart->regs.iir = UART_IIR_RLSI;
} else if ((uart->regs.ier & UART_IER_RDI) /* RD available */
&& (uart->istat.rxbuf_full >= UART_FIFO_TRIGGER(uart->regs.fcr >> 6))
&& (uart->regs.lsr & UART_LSR_RDRDY)) {
uart->regs.iir = UART_IIR_RDI;
} else if ((uart->regs.ier & UART_IER_RDI) /* timeout */
&& (uart->istat.timeout_count >= UART_CHAR_TIMEOUT * uart->char_clks)
&& (uart->istat.rxbuf_head != uart->istat.rxbuf_tail)) {
uart->regs.iir = UART_IIR_CTI;
} else if (uart->regs.ier & UART_IER_THRI && /* Transm. empty */
uart->istat.thre_int == 1) {
uart->regs.iir = UART_IIR_THRI;
} else if (uart->regs.ier & UART_IER_MSI && /* Modem status */
uart->regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
| UART_MSR_TERI | UART_MSR_DDCD)) {
uart->regs.iir = UART_IIR_MSI;
}
if (!(uart->regs.iir & UART_IIR_NO_INT)) {
TRACE("\tuart->regs.iir = %i\t", uart->regs.iir);
report_interrupt(uart->irq);
}
}
 
/* 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: UART has problems with channel \"%s\".\n", uart->channel_str);
} else if (config.sim.verbose)
PRINTF("UART at 0x%"PRIxADDR" uses ", 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.txser_full = uart->istat.rxser_full = 0;
uart->istat.txbuf_full = uart->istat.rxbuf_full = 0;
 
uart->istat.txser_clks = uart->istat.rxser_clks = 0;
 
uart->istat.thre_int = 0;
uart->istat.break_set = 0;
uart->istat.timeout_count = 0;
 
// For FIFO-mode only, THRE interrupt is set when both THR and FIFO are empty
uart->istat.thre_int = (uart->fifo_len == 16);
 
uart->char_clks = 0;
uart->slowdown = UART_FGETC_SLOWDOWN;
 
uart->iregs.txser = 0;
uart->iregs.rxser = 0;
uart->iregs.loopback = 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 = 0;
uart->regs.fcr = 0;
uart->regs.lcr = UART_LCR_RESET;
uart->regs.mcr = 0;
uart->regs.lsr = 0;
uart->regs.msr = 0;
uart->regs.scr = 0;
 
uart->vapi.cur_break = uart->vapi.cur_break_cnt = uart->vapi.next_break = 0;
uart->vapi.next_break_cnt = -1;
uart->vapi.break_sent = 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));
 
SCHED_ADD (uart_clock16, dat, UART_CLOCK_DIVIDER);
}
 
/* 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: %.2lx TXSER: %.2lx\n", uart->iregs.rxser, uart->iregs.txser);
 
PRINTF("\nInternal status (sim debug):\n");
PRINTF("char_clks: %ld\n", uart->char_clks);
PRINTF("rxser_clks: %ld txser_clks: %ld\n", uart->istat.rxser_clks,
uart->istat.txser_clks);
PRINTF("rxser: %d txser: %d\n", uart->istat.rxser_full, uart->istat.txser_full);
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_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->channel_str = NULL;
new->channel = NULL;
new->vapi_id = 0;
 
return new;
}
 
void uart_sec_end(void *dat)
{
struct dev_16450 *uart = dat;
 
register_memoryarea(uart->baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte,
uart_write_byte, dat);
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, "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);
}
/gpio.c
0,0 → 1,287
/* 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 <string.h>
 
#include "config.h"
 
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#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"
 
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 );
 
/* 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 );
}
}
}
 
 
/* 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;
 
addr -= gpio->baseaddr;
 
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;
 
addr -= gpio->baseaddr;
 
switch( addr ) {
case RGPIO_IN: debug( 5, "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;
 
debug( 5, "GPIO: id %08lx, data %08lx\n", id, data );
 
which = id - gpio->base_vapi_id;
 
switch( which ) {
case GPIO_VAPI_DATA:
debug( 4, "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;
}
 
/* Clock the device */
if ( !(gpio->curr.ctrl & RGPIO_CTRL_ECLK) )
gpio_device_clock( gpio );
}
 
/* 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 ) {
debug( 4, "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 ) {
debug( 4, "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 ) {
debug( 3, "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_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));
 
return new;
}
 
void gpio_sec_end(void *dat)
{
struct gpio_device *gpio = dat;
 
/* Register memory range */
register_memoryarea( gpio->baseaddr, GPIO_ADDR_SPACE, 4, 0, gpio_read32, gpio_write32, dat );
 
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, "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);
}
/eth.c
0,0 → 1,902
/* 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"
 
/* 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_rewind_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 breakpoint = 0;
int bAdvance = 1;
#if HAVE_ETH_PHY
struct sockaddr_ll sll;
#endif /* HAVE_ETH_PHY */
long nwritten;
unsigned long read_word;
 
switch (eth->tx.state) {
case ETH_TXSTATE_IDLE:
debug (3, "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 */
debug( 3, "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 */
debug (3, "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, &breakpoint, 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, &breakpoint, 0, 0);
eth->tx.bytes_sent += 1;
}
#endif
else {
debug (3, "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);
debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
debug (3, "TX - entering state WAIT4BD\n");
eth->tx.state = ETH_TXSTATE_WAIT4BD;
debug (3, "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);
debug (4, "ETH_INT_SOURCE = %0lx\n", eth->regs.int_source);
debug (3, "TX - entering state WAIT4BD\n");
eth->tx.state = ETH_TXSTATE_WAIT4BD;
debug (3, "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;
int breakpoint = 0;
long nread;
unsigned long send_word;
switch (eth->rx.state) {
case ETH_RXSTATE_IDLE:
debug (3, "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 );
debug( 3, "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;
}
debug (3, "RX - entering state RECV\n");
eth->rx.state = ETH_RXSTATE_RECV;
}
else if (!TEST_FLAG( eth->regs.moder, ETH_MODER, RXEN)) {
debug (3, "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) */
debug (4, "eth_start_rx(): File does not have a packet ready for RX (len = %ld)\n", eth->rx.packet_length );
runtime.sim.cont_run = 0;
break;
}
 
/* Packet must be big enough to hold a header */
if ( eth->rx.packet_length < ETHER_HDR_LEN ){
debug( 3, "eth_start_rx(): Packet too small\n" );
eth_rx_next_packet( eth );
 
debug (3, "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 ) {
debug (3, "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;
 
debug (3, "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)
break;
else if (nread < 0) {
if ( errno != EAGAIN ) {
debug (3, "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;
debug (3, "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, &breakpoint, 0, 0);
/* update counters */
debug (3, "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], &breakpoint, 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);
debug (4, "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 */
debug (3, "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;
}
 
/* Move RX file position back */
void eth_rewind_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 ) {
debug( 3, "Ethernet: No RX file\n" );
return 0;
}
if ( eth->rx.offset )
if ( lseek( eth->rx.fd, *(eth->rx.offset), SEEK_SET ) == (off_t)-1 ) {
debug( 3, "Ethernet: Error seeking RX file\n" );
return 0;
}
 
result = read( eth->rx.fd, buf, count );
debug (4, "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;
debug (3, "RTX oppening 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 */
debug (3, "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;
}
debug (3, "RTX Socket Interface : %d\n", eth->ifr.ifr_ifindex);
/* Bind to interface... */
debug (3, "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. */
debug (3, "Flush");
do {
fd_set fds;
struct timeval t;
debug( 3, ".");
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);
debug (3, "\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;
addr -= eth->baseaddr;
 
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 );
runtime.sim.cont_run = 0;
return 0;
}
/* ========================================================================= */
 
 
/*
Write a register
*/
void eth_write32( oraddr_t addr, uint32_t value, void *dat )
{
struct eth_device *eth = dat;
 
addr -= eth->baseaddr;
 
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 );
runtime.sim.cont_run = 0;
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;
 
debug( 5, "ETH: id %08lx, data %08lx\n", id, data );
 
if ( !eth ) {
debug( 1, "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_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);
}
 
return new;
}
 
void eth_sec_end(void *dat)
{
struct eth_device *eth = dat;
 
register_memoryarea( eth->baseaddr, ETH_ADDR_SPACE, 4, 0, eth_read32, eth_write32, dat );
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, "baseaddr", paramt_int, 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);
}
/ps2kbd.c
0,0 → 1,352
/* 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 <stdlib.h>
#include <stdio.h>
#include <string.h>
 
#include "config.h"
 
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#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 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, uint32_t value, void *dat)
{
struct kbd_state *kbd = dat;
int a = (addr - kbd->baseaddr);
switch (a) {
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);
runtime.sim.cont_run = 0;
break;
}
}
 
/* Read a register */
uint32_t kbd_read8 (oraddr_t addr, void *dat)
{
struct kbd_state *kbd = dat;
int a = (addr - kbd->baseaddr);
switch (a) {
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;
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);
runtime.sim.cont_run = 0;
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: Keyboard has problems with 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_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;
 
return new;
}
 
void kbd_sec_end(void *dat)
{
struct kbd_state *kbd = dat;
 
register_memoryarea(kbd->baseaddr, KBD_SPACE, 1, 0, kbd_read8, kbd_write8, dat);
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_int, kbd_baseaddr);
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: fb.c =================================================================== --- fb.c (nonexistent) +++ fb.c (revision 1765) @@ -0,0 +1,376 @@ +/* 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 { + 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; + + oraddr_t a = (addr - fb->baseaddr); + + switch (a) { + 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: + a -= FB_PAL; + a /= 4; + if (a < 0 || a >= 256) { + fprintf (stderr, "Write out of palette buffer (0x%"PRIxADDR")!\n", addr); + runtime.sim.cont_run = 0; + } else fb->pal[a] = value; + break; + } +} + +/* Read a register */ +oraddr_t fb_read32 (oraddr_t addr, void *dat) +{ + struct fb_state *fb = dat; + + oraddr_t a = (addr - fb->baseaddr); + + switch (a) { + 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: + a -= FB_PAL; + a /= 4; + if (a < 0 || a >= 256) { + fprintf (stderr, "Read out of palette buffer (0x%"PRIxADDR")!\n", addr); + runtime.sim.cont_run = 0; + return 0; + } else return fb->pal[a]; + } +} + +/* 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, y; + 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 (evalsim_mem8 (add), 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, y; + 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 = evalsim_mem16 (add); + 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[evalsim_mem8 (add)]; + 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 VGAs */ +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_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; + + return new; +} + +void fb_sec_end(void *dat) +{ + struct fb_state *fb = dat; + + if (fb->baseaddr) + register_memoryarea(fb->baseaddr, FB_PAL + 256*4, 4, 0, fb_read32, fb_write32, dat); + + 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, "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: vga.c =================================================================== --- vga.c (nonexistent) +++ vga.c (revision 1765) @@ -0,0 +1,297 @@ +/* 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 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; + + addr -= vga->baseaddr; + + 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); + runtime.sim.cont_run = 0; + return; + } + break; + } +} + +/* Read a register */ +uint32_t vga_read32(oraddr_t addr, void *dat) +{ + struct vga_state *vga = dat; + + addr -= vga->baseaddr; + + 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); + runtime.sim.cont_run = 0; + 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, y; + 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 = evalsim_mem32 (vga->vbar[vga->vbindex] + (y * sx + x) * (bpp + 1)); + 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_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; + + return new; +} + +void vga_sec_end(void *dat) +{ + struct vga_state *vga = dat; + + if (vga->baseaddr) + register_memoryarea(vga->baseaddr, VGA_ADDR_SPACE, 4, 0, vga_read32, vga_write32, dat); + + 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, "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: Makefile.in =================================================================== --- Makefile.in (nonexistent) +++ Makefile.in (revision 1765) @@ -0,0 +1,454 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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. +# +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_alias = @build_alias@ +build_triplet = @build@ +host_alias = @host_alias@ +host_triplet = @host@ +target_alias = @target_alias@ +target_triplet = @target@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +AWK = @AWK@ +BUILD_DIR = @BUILD_DIR@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CPU_ARCH = @CPU_ARCH@ +DEPDIR = @DEPDIR@ +INCLUDES = @INCLUDES@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LOCAL_CFLAGS = @LOCAL_CFLAGS@ +LOCAL_DEFS = @LOCAL_DEFS@ +MAKE_SHELL = @MAKE_SHELL@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +STRIP = @STRIP@ +SUMVERSION = @SUMVERSION@ +TERMCAP_LIB = @TERMCAP_LIB@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +host = @host@ +host_cpu = @host_cpu@ +host_os = @host_os@ +install_sh = @install_sh@ + +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 \ +test.c + +subdir = peripheral +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libperipheral_a_AR = $(AR) cru +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) test.$(OBJEXT) +libperipheral_a_OBJECTS = $(am_libperipheral_a_OBJECTS) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/16450.Po ./$(DEPDIR)/atadevice.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/atadevice_cmdi.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/atahost.Po ./$(DEPDIR)/crc32.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/dma.Po ./$(DEPDIR)/eth.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/fb.Po ./$(DEPDIR)/gpio.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/mc.Po ./$(DEPDIR)/ps2kbd.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/test.Po ./$(DEPDIR)/vga.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libperipheral_a_SOURCES) + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = Makefile.am Makefile.in +DIST_SUBDIRS = $(SUBDIRS) +SOURCES = $(libperipheral_a_SOURCES) + +all: all-recursive + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu peripheral/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +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) core *.core + +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)/ps2kbd.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vga.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `cygpath -w $<` +CCDEPMODE = @CCDEPMODE@ +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): + @set fnord $$MAKEFLAGS; amf=$$2; \ + 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) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + 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: + @set fnord $$MAKEFLAGS; amf=$$2; \ + 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) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +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-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$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; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_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 +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + 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"; \ + $(mkinstalldirs) "$(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='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (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_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(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 + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-recursive + +dvi-am: + +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 + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-noinstLIBRARIES clean-recursive distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-recursive distclean-tags distdir dvi dvi-am \ + dvi-recursive info info-am info-recursive install install-am \ + install-data install-data-am install-data-recursive \ + install-exec install-exec-am install-exec-recursive \ + install-info install-info-am install-info-recursive install-man \ + install-recursive install-strip installcheck installcheck-am \ + installdirs installdirs-am installdirs-recursive \ + maintainer-clean maintainer-clean-generic \ + maintainer-clean-recursive mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-recursive tags tags-recursive \ + uninstall uninstall-am uninstall-info-am \ + uninstall-info-recursive uninstall-recursive + +# 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: Index: channels/Makefile.in =================================================================== --- channels/Makefile.in (nonexistent) +++ channels/Makefile.in (revision 1765) @@ -0,0 +1,349 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# 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 +# +# 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. +# +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_alias = @build_alias@ +build_triplet = @build@ +host_alias = @host_alias@ +host_triplet = @host@ +target_alias = @target_alias@ +target_triplet = @target@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AR = @AR@ +ARFLAGS = @ARFLAGS@ +AWK = @AWK@ +BUILD_DIR = @BUILD_DIR@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CPU_ARCH = @CPU_ARCH@ +DEPDIR = @DEPDIR@ +INCLUDES = @INCLUDES@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LOCAL_CFLAGS = @LOCAL_CFLAGS@ +LOCAL_DEFS = @LOCAL_DEFS@ +MAKE_SHELL = @MAKE_SHELL@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +STRIP = @STRIP@ +SUMVERSION = @SUMVERSION@ +TERMCAP_LIB = @TERMCAP_LIB@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +host = @host@ +host_cpu = @host_cpu@ +host_os = @host_os@ +install_sh = @install_sh@ + +noinst_LIBRARIES = libchannels.a +libchannels_a_SOURCES = \ +channel.c \ +fd.c \ +file.c \ +generic.c \ +xterm.c \ +tcp.c \ +tty.c + +subdir = peripheral/channels +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + +libchannels_a_AR = $(AR) cru +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) + +DEFS = @DEFS@ +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/channel.Po ./$(DEPDIR)/fd.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/file.Po ./$(DEPDIR)/generic.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/tcp.Po ./$(DEPDIR)/tty.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/xterm.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libchannels_a_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(libchannels_a_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu peripheral/channels/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +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) core *.core + +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@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `cygpath -w $<` +CCDEPMODE = @CCDEPMODE@ +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +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: $(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 "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_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 +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = ../.. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + 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"; \ + $(mkinstalldirs) "$(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_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(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 + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-tags + +dvi: dvi-am + +dvi-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 + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-noinstLIBRARIES distclean distclean-compile \ + distclean-depend distclean-generic distclean-tags distdir dvi \ + dvi-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 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: Index: channels/channel.c =================================================================== --- channels/channel.c (nonexistent) +++ channels/channel.c (revision 1765) @@ -0,0 +1,256 @@ +/* channel.h -- Definition of types and structures for + peripheral to communicate with host. Addapted from UML. + + Copyright (C) 2002 Richard Prescott + +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 /* perror */ +#include /* exit */ + +#if HAVE_MALLOC_H +#include /* calloc, free */ +#endif + +#include /* strndup, strcmp, strlen, strchr */ +#include /* 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: + */ + Index: channels/xterm.c =================================================================== --- channels/xterm.c (nonexistent) +++ channels/xterm.c (revision 1765) @@ -0,0 +1,265 @@ +/* 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 + +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 +#endif + +#define _XOPEN_SOURCE /* grantpt() and al. */ +#define _GNU_SOURCE /* on_exit */ + +#include /* waitpid() */ +#include /* waitpid() */ +#include /* sprintf() */ +#include /* kill(), on_exit() */ +#include /* close() */ +#include /* O_RDWR */ +#include /* strchr() */ + +#ifndef __CYGWIN__ +#if HAVE_SYS_STROPTS_H +#include /* grantpt(), unlockpt() */ +#endif +#include /* basename() */ +#endif /* __CYGWIN__ */ + +#include /* struct termios and al. */ +#include /* signal() and al. */ +#include /* 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; + +} + +static void xterm_exit(int i, void * data) +{ + xterm_close(data); +} + +#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: + */ + Index: channels/tty.c =================================================================== --- channels/tty.c (nonexistent) +++ channels/tty.c (revision 1765) @@ -0,0 +1,196 @@ +/* tty.c -- Definition of functions for peripheral to + * communicate with host via a tty. + + Copyright (C) 2002 Richard Prescott + +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 +#include +#include + +#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, 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; +} + +static int tty_read(void * data, char * buffer, int size) +{ + return fd_read(data, buffer, size); +} + +static int tty_write(void * data, const char * buffer, int size) +{ + return fd_write(data, buffer, size); +} + +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: + */ + Index: channels/tcp.c =================================================================== --- channels/tcp.c (nonexistent) +++ channels/tcp.c (revision 1765) @@ -0,0 +1,181 @@ +/* tcp.c -- Definition of functions for peripheral to + * communicate with host via a tcp socket. + + Copyright (C) 2002 Richard Prescott + +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 +#include +#include +#include +#include +#include + +#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, 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: + */ + Index: channels/file.c =================================================================== --- channels/file.c (nonexistent) +++ channels/file.c (revision 1765) @@ -0,0 +1,162 @@ +/* file.c -- Definition of functions and structures for + peripheral to communicate with host through files + + Copyright (C) 2002 Richard Prescott + +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 +#endif + +#define _GNU_SOURCE /* for strndup */ + +#include /* open() */ +#include /* open() */ +#include /* open() */ +#if HAVE_MALLOC_H +#include /* calloc, free */ +#endif +#include /* strndup(), strchr() */ +#include /* errno */ +#include /* 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: + */ Index: channels/fd.c =================================================================== --- channels/fd.c (nonexistent) +++ channels/fd.c (revision 1765) @@ -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 + +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 +#endif + +#include /* struct timeval */ +#include /* fd_set */ +#include /* perror */ +#include /* atoi */ +#include /* read, write, select */ +#if HAVE_MALLOC_H +#include /* calloc, free */ +#endif +#include /* strchr */ +#include /* 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: + */ Index: channels/generic.c =================================================================== --- channels/generic.c (nonexistent) +++ channels/generic.c (revision 1765) @@ -0,0 +1,61 @@ +/* generic.c -- Definition of generic functions for peripheral to + * communicate with host + + Copyright (C) 2002 Richard Prescott + +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 +#endif + +#if HAVE_MALLOC_H +#include /* calloc, free */ +#endif + +#include /* 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: + */ Index: channels/Makefile.am =================================================================== --- channels/Makefile.am (nonexistent) +++ channels/Makefile.am (revision 1765) @@ -0,0 +1,30 @@ +# Makefile -- Makefile for peripherals channels to host +# Copyright (C) 2002 Richard Prescott +# +# 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 + Index: channels/fd.h =================================================================== --- channels/fd.h (nonexistent) +++ channels/fd.h (revision 1765) @@ -0,0 +1,34 @@ +/* generic.h -- Declaration of generic functions for peripheral to + * communicate with host + + Copyright (C) 2002 Richard Prescott + +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 Index: channels/generic.h =================================================================== --- channels/generic.h (nonexistent) +++ channels/generic.h (revision 1765) @@ -0,0 +1,29 @@ +/* generic.h -- Declaration of generic functions for peripheral to + * communicate with host + + Copyright (C) 2002 Richard Prescott + +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 Index: channels/channel.h =================================================================== --- channels/channel.h (nonexistent) +++ channels/channel.h (revision 1765) @@ -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 + +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: + */ Index: channels =================================================================== --- channels (nonexistent) +++ channels (revision 1765)
channels Property changes : Added: svn:ignore ## -0,0 +1,2 ## +Makefile +.deps 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: mc.c =================================================================== --- mc.c (nonexistent) +++ mc.c (revision 1765) @@ -0,0 +1,250 @@ +/* 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" + +extern struct dev_memarea *dev_list; + +void set_csc_tms (int cs, unsigned long csc, unsigned long tms, struct mc *mc) { + struct dev_memarea *mem_dev = dev_list; + + while (mem_dev) { + if (mem_dev->chip_select == cs) { + mem_dev->addr_mask = mc->ba_mask << 22; + mem_dev->addr_compare = ((csc >> MC_CSC_SEL_OFFSET) /* & 0xff*/) << 22; + mem_dev->valid = (csc >> MC_CSC_EN_OFFSET) & 0x01; + + if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_ASYNC) { + mem_dev->delayr = (tms & 0xff) + ((tms >> 8) & 0x0f); + mem_dev->delayw = ((tms >> 12) & 0x0f) + ((tms >> 16) & 0x0f) + ((tms >> 20) & 0x3f); + } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SDRAM) { + mem_dev->delayr = 3 + ((tms >> 4) & 0x03); + mem_dev->delayw = 3 + ((tms >> 4) & 0x03); + } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SSRAM) { + mem_dev->delayr = 2; + mem_dev->delayw = 2; + } else if ((csc >> MC_CSC_MEMTYPE_OFFSET) && 0x07 == MC_CSC_MEMTYPE_SYNC) { + mem_dev->delayr = 2; + mem_dev->delayw = 2; + } + return; + } + mem_dev = mem_dev->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; + + debug(5, "mc_write_word(%"PRIxADDR",%08"PRIx32")\n", addr, value); + + addr -= mc->baseaddr; + + switch (addr) { + case MC_CSR: + mc->csr = value; + break; + case MC_POC: + fprintf (stderr, "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 + debug(1, "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; + + debug(5, "mc_read_word(%"PRIxADDR")", addr); + + addr -= mc->baseaddr; + + 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 + debug(1, " read out of range (addr %"PRIxADDR")\n", addr + mc->baseaddr); + break; + } + debug(5, " value(%"PRIx32")\n", value); + return value; +} + +/* Read POC register and init memory controler regs. */ +void mc_reset(void *dat) +{ + struct mc *mc = dat; + struct dev_memarea *mem_dev = dev_list; + + 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; + } + + while (mem_dev) { + mem_dev->valid = 0; + mem_dev = mem_dev->next; + } + + 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%08lX\n", mc->poc ); + PRINTF( "BAS: 0x%08lX\n", mc->ba_mask ); + PRINTF( "CSR: 0x%08lX\n", mc->csr ); + + for (i=0; icsc[i], + mc->tms[i]); + } +} + +/*-----------------------------------------------------[ 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_sec_start(void) +{ + struct mc *new = malloc(sizeof(struct mc)); + + if(!new) { + fprintf(stderr, "Peripheral MC: Run out of memory\n"); + exit(-1); + } + + new->enabled = 0; + + return new; +} + +void mc_sec_end(void *dat) +{ + struct mc *mc = dat; + + if(mc->enabled) { + register_memoryarea(mc->baseaddr, MC_ADDR_SPACE, 4, 1, mc_read_word, mc_write_word, dat); + 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); +}
mc.c 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,121 @@ +/* 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 + +struct mc { + unsigned long csr; + unsigned long poc; + unsigned long ba_mask; + unsigned long csc[N_CE]; + unsigned long tms[N_CE]; + oraddr_t baseaddr; + int enabled; +}; + +#endif
mc.h Property changes : Added: svn:executable ## -0,0 +1 ## +* \ No newline at end of property Index: ethernet_i.h =================================================================== --- ethernet_i.h (nonexistent) +++ ethernet_i.h (revision 1765) @@ -0,0 +1,222 @@ +/* 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 +{ + /* 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: 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: dma.h =================================================================== --- dma.h (nonexistent) +++ dma.h (revision 1765) @@ -0,0 +1,96 @@ +/* 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 +{ + /* 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: 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: 16450.h =================================================================== --- 16450.h (nonexistent) +++ 16450.h (revision 1765) @@ -0,0 +1,224 @@ +/* 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 { + unsigned txbuf[UART_MAX_FIFO_LEN]; + unsigned rxbuf[UART_MAX_FIFO_LEN]; + unsigned char dll; + unsigned char dlh; + unsigned char ier; + unsigned char iir; + unsigned char fcr; + unsigned char lcr; + unsigned char mcr; + unsigned char lsr; + unsigned char msr; + unsigned char scr; + } regs; /* Visible registers */ + struct { + unsigned long txser; /* Character just sending */ + unsigned long rxser; /* Character just receiving */ + unsigned char loopback; + } iregs; /* Internal registers */ + struct { + int txbuf_head; + int txbuf_tail; + int rxbuf_head; + int rxbuf_tail; + unsigned int txser_full; + unsigned int rxser_full; + unsigned int txbuf_full; + unsigned int rxbuf_full; + unsigned thre_int; + unsigned break_set; + unsigned long txser_clks; + unsigned long rxser_clks; + unsigned timeout_count; + } istat; /* Internal status */ + + /* Clocks per char */ + unsigned long char_clks; + + /* VAPI internal registers */ + struct { + unsigned long char_clks; + int dll, dlh; + int lcr; + int skew; + int next_break; + int next_break_cnt; + int cur_break; + int cur_break_cnt; + int break_sent; + } 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; + + /* fgetc slowdown */ + int slowdown; + + struct channel *channel; + + /* Configuration */ + 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: atadevice.c =================================================================== --- atadevice.c (nonexistent) +++ atadevice.c (revision 1765) @@ -0,0 +1,571 @@ +/* + 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 "messages.h" +#include "atadevice.h" +#include "atacmd.h" +#include "sim-config.h" +#include "atadevice_cmdi.h" + +/* + 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: + MSG_NOTE("ata_device, using type NO_CONNECT."); + device->stream = NULL; + break; + + case TYPE_FILE: + MSG_NOTE("ata_device, using device type FILE."); + device->stream = open_file(&device->size, device->file); + break; + + case TYPE_LOCAL: + MSG_NOTE("ata_device, using device type LOCAL."); + device->stream = open_local(); + break; + + default: + MSG_FATAL("ata_device, illegal device-type."); + MSG_EMPTY("defaulting to type NO_CONNECT."); + 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+")) ) + { + MSG_FATAL( strcat("ata_open_file, cannot open hd-file ", filename) ); + return NULL; + } + else + { + /* TODO create a file 'size' large */ + /* create a file 'size' large */ + MSG_NOTE("ata_device; generating a new hard disk file."); + MSG_EMPTY("This may take a while, depending on the requested size."); + 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); + + + ata_device_debug(1, "requested filesize was: %d (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); + + ata_device_debug(1, "actual filesize is: %d (MBytes).\n", *size >> 20); + + return fp; +} + + +/* Use a the local filesystem as a hard-disk */ +FILE *open_local(void) +{ + // TODO: + MSG_WARNING("ata_device; device type LOCAL is not supported yet."); + MSG_EMPTY("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 */ + ata_device_debug(2, "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 */ + ata_device_debug(1, "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 */ + ata_device_debug(2, "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 */ + ata_device_debug(2, "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) + MSG_WARNING("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) ) + MSG_ERROR("ata_devices_read, no ata devices connected."); + 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 : + ata_device_debug(4, "alternate_status register read\n"); + if ( (device->regs.device_head & ATA_DHR_DEV) == device->internals.dev ) + return device -> regs.status; + else + { + ata_device_debug(2, "device0 responds for device1, asr = 0x00\n"); + return 0; // return 0 when device0 responds for device1 + } + + case ATA_CHR : + ata_device_debug(4, "cylinder_high register read, value = 0x%02X\n", + device->regs.cylinder_high); + return device -> regs.cylinder_high; + + case ATA_CLR : + ata_device_debug(4, "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) + { + ata_device_debug(1, "data register read, while DRQ bit negated\n" ); + return 0; + } + else + { + ata_device_debug(4, "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 : + ata_device_debug(4, "device_head register read, value = 0x%02X\n", + device->regs.device_head); + return device -> regs.device_head; + + case ATA_ERR : + ata_device_debug(4, "error register read, value = 0x%02X\n", + device->regs.error); + return device -> regs.error; + + case ATA_SCR : + ata_device_debug(4, "sectorcount register read, value = 0x%02X\n", + device->regs.sector_count); + return device -> regs.sector_count; + + case ATA_SNR : + ata_device_debug(4, "sectornumber register read, value = 0x%02X\n", + device->regs.sector_number); + return device -> regs.sector_number; + + case ATA_SR : + ata_device_debug(4, "status register read\n"); + if ( (device->regs.device_head & ATA_DHR_DEV) == device->internals.dev) + return device -> regs.status; + else + { + ata_device_debug(2, "device0 responds for device1, sr = 0x00\n"); + return 0; // return 0 when device0 responds for device1 + } + +// case ATA_DA : +// return device -> regs.status; + } + } +} + + +/* + 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) + MSG_ERROR("ata_devices_write, no ata devices connected."); + 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 */ + ata_device_debug(4, "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 */ + ata_device_debug(4, "cylinder high register written, value = 0x%02X\n", value); + + device->regs.cylinder_high = value; + break; + + case ATA_CLR : + /*display debug information */ + ata_device_debug(4, "cylinder low register written, value = 0x%02X\n", value); + + device->regs.cylinder_low = value; + break; + + case ATA_DR : + /*display debug information */ + ata_device_debug(4, "data register written, value = 0x%04X\n", value); + + device->regs.dataport_i = value; + break; + + case ATA_DCR : + /*display debug information */ + ata_device_debug(4, "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 */ + ata_device_debug(4, "device head register written, value = 0x%02X\n", value); + + device->regs.device_head = value; + break; + + case ATA_FR : + /*display debug information */ + ata_device_debug(4, "features register written, value = 0x%02X\n", value); + + device->regs.features = value; + break; + + case ATA_SCR : + /*display debug information */ + ata_device_debug(4, "sectorcount register written, value = 0x%02X\n", value); + + device->regs.sector_count = value; + break; + + case ATA_SNR : + /*display debug information */ + ata_device_debug(4, "sectornumber register written, value = 0x%02X\n", value); + + device->regs.sector_number = value; + break; + + } //endcase +} + + +/* -------------------------- */ +/* -- print debug messages -- */ +/* -------------------------- */ +int ata_device_debug(int lvl, char *format, ...) +{ + va_list ap; + + va_start(ap, format); + + if (ATA_DEVICE_DEBUG_LVL >= lvl) + { + fprintf(stderr, "ata_device_debug: "); + vfprintf(stderr, format, ap); + } + + va_end(ap); + return 0; +} Index: atadevice.h =================================================================== --- atadevice.h (nonexistent) +++ atadevice.h (revision 1765) @@ -0,0 +1,215 @@ +/* + 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 + +/* + ata device debug level + 0: don't display debug information + 1: display general (debug) information + 2: display program flow control information + 3: display internal statemachine flow information + 4: display all debug information +*/ +#define ATA_DEVICE_DEBUG_LVL 4 + + +/* --- 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; + + +/* ------------------------------ */ +/* ----- Device Prototypes ----- */ +/* ------------------------------ */ +int ata_device_debug(int lvl, char *format, ...); + +/* 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: atahost.c =================================================================== --- atahost.c (nonexistent) +++ atahost.c (revision 1765) @@ -0,0 +1,360 @@ +/* + 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 'register_memoryarea()', 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" +#include "messages.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->baseaddr, 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; + + addr -= ata->baseaddr; + + /* determine if ata_host or ata_device addressed */ + if (is_ata_hostadr(addr)) + { + // Accesses to internal register take 2cycles + adjust_rw_delay( ata->baseaddr, 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->baseaddr, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) ); + else + adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) ); + } + else +#endif + adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) ); + + return ata_devices_read(&ata->devices, addr & 0x7f); + } +} +/* ========================================================================= */ + + +/* + Write a register +*/ +void ata_write32( oraddr_t addr, uint32_t value, void *dat ) +{ + ata_host *ata = dat; + + addr -= ata->baseaddr; + + /* determine if ata_host or ata_device addressed */ + if (is_ata_hostadr(addr)) + { + // Accesses to internal register take 2cycles + adjust_rw_delay( ata->baseaddr, 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->baseaddr, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) ); + else + adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) ); + } + else +#endif + adjust_rw_delay( ata->baseaddr, 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_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)); + return new; +} + +void ata_sec_end(void *dat) +{ + ata_host *ata = dat; + + /* Connect ata_devices. */ + ata_devices_init(&ata->devices); + + register_memoryarea(ata->baseaddr, ATA_ADDR_SPACE, 4, 0, ata_read32, ata_write32, dat); + + 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, "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: atahost.h =================================================================== --- atahost.h (nonexistent) +++ atahost.h (revision 1765) @@ -0,0 +1,146 @@ +/* + 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{ + /* Base address in memory */ + oraddr_t baseaddr; + + /* 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: test.c =================================================================== --- test.c (nonexistent) +++ test.c (revision 1765) @@ -0,0 +1,87 @@ +#include + +#include "config.h" + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#include "port.h" +#include "arch.h" +#include "sim-config.h" +#include "abstract.h" +#include "except.h" + +struct test_config { + uint32_t array[128]; + oraddr_t baseaddr; +}; + +/* Test write */ +void test_write32 (oraddr_t addr, uint32_t value, void *dat) +{ + struct test_config *test = dat; + + if (addr & 0x00000080) + test->array[addr & 0x7f] = value; + else + except_handle(EXCEPT_BUSERR, cur_vadd); +} + +/* Test read */ +uint32_t test_read32 (oraddr_t addr, void *dat) +{ + struct test_config *test = dat; + + if (addr & 0x00000080) + return ~test->array[addr & 0x7f]; + else + except_handle(EXCEPT_BUSERR, cur_vadd); + return 0x00000000; +} + +void test_reset (void *dat) +{ + struct test_config *test = dat; + int i; + + for (i = 0; i < 128; i++) + test->array[i] = 0x00000000; +} + +/*---------------------------------------------------[ Test configuration ]---*/ +void test_baseaddr(union param_val val, void *dat) +{ + struct test_config *test = dat; + test->baseaddr = val.addr_val; +} + +void *test_sec_start(void) +{ + struct test_config *test = malloc(sizeof(struct test_config)); + + if(!test) { + fprintf(stderr, "Peripheral Test: Run out of memory\n"); + exit(-1); + } + + test->baseaddr = 0; + + return test; +} + +void test_sec_end(void *dat) +{ + struct test_config *test = dat; + if(test->baseaddr) + register_memoryarea(test->baseaddr, 256, 4, 0, test_read32, test_write32, NULL); + reg_sim_reset(test_reset, dat); +} + +void reg_test_sec(void) +{ + struct config_section *sec = reg_config_sec("test", test_sec_start, + test_sec_end); + + reg_config_param(sec, "baseaddr", paramt_addr, test_baseaddr); +} 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: gpio_i.h =================================================================== --- gpio_i.h (nonexistent) +++ gpio_i.h (revision 1765) @@ -0,0 +1,80 @@ +/* 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 +{ + /* 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: atadevice_cmdi.c =================================================================== --- atadevice_cmdi.c (nonexistent) +++ atadevice_cmdi.c (revision 1765) @@ -0,0 +1,928 @@ +/* + 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 "messages.h" +#include "atadevice.h" +#include "atadevice_cmdi.h" +#include "atacmd.h" + +int ata_device_execute_cmd(ata_device *device) +{ + /*display debug information */ + ata_device_debug(2, "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 */ + ata_device_debug(2, "executing command 'device reset'\n"); + + if (!device->packet) + MSG_WARNING("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 */ + ata_device_debug(2, "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 */ + ata_device_debug(2, "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 = (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. + */ + ata_device_debug(1, "'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 */ + ata_device_debug(2, "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 */ + ata_device_debug(2, "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. + */ + ata_device_debug(1, "'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: 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 \ +test.c 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: messages.h =================================================================== --- messages.h (nonexistent) +++ messages.h (revision 1765) @@ -0,0 +1,36 @@ +/* + messages.h + 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. +*/ + +/* + * macros for generating standard messages + */ + +#ifndef __OR1KSIM_MESSAGES_H +#define __OR1KSIM_MESSAGES_H + +#define MSG_DEBUG(message) fprintf(stderr, "DEBUG : %s\n", message) +#define MSG_EMPTY(message) fprintf(stderr, " %s\n", message) +#define MSG_ERROR(message) fprintf(stderr, "ERROR : %s\n", message) +#define MSG_FATAL(message) fprintf(stderr, "FATAL : %s\n", message) +#define MSG_NOTE(message) fprintf(stderr, "NOTE : %s\n", message) +#define MSG_WARNING(message) fprintf(stderr, "WARNING: %s\n", message) + +#endif 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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.