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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc2/] [or1ksim/] [peripheral/] [atahost.c] - Diff between revs 970 and 997

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 970 Rev 997
/*
/*
    atahost.c -- ATA Host code simulation
    atahost.c -- ATA Host code simulation
    Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
    Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
 
 
    This file is part of OpenRISC 1000 Architectural Simulator
    This file is part of OpenRISC 1000 Architectural Simulator
 
 
    This program is free software; you can redistribute it and/or modify
    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
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version
    (at your option) any later version
 
 
    This program is distributed in the hope that it will be useful,
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    GNU General Public License for more details.
 
 
    You should have received a copy of the GNU General Public License
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
*/
 
 
/* get a prototype for 'register_memoryarea()', and 'adjust_rw_delay()' */
/* get a prototype for 'register_memoryarea()', and 'adjust_rw_delay()' */
#include "abstract.h"
#include "abstract.h"
#include "sim-config.h"
#include "sim-config.h"
#include "sched.h"
#include "sched.h"
 
 
/* all user defineable settings are in 'atahost_define.h'             */
/* all user defineable settings are in 'atahost_define.h'             */
#include "atahost_define.h"
#include "atahost_define.h"
#include "atahost.h"
#include "atahost.h"
#include "messages.h"
#include "messages.h"
 
 
static ata_host atas[MAX_ATAS];
static ata_host atas[MAX_ATAS];
 
 
/* reset and initialize ATA host core(s) */
/* reset and initialize ATA host core(s) */
void ata_reset(void)
void ata_reset(void)
{
{
   static int first_time=0;
   static int first_time=0;
 
 
   unsigned i;
   unsigned i;
   ata_host *ata;
   ata_host *ata;
 
 
   // for all ATA cores
   // for all ATA cores
   for (i=0; i < config.natas; i++)
   for (i=0; i < config.natas; i++)
   {
   {
     ata = &(atas[i]);
     ata = &(atas[i]);
 
 
     // reset the core registers
     // reset the core registers
     ata->regs.ctrl  = 0x0001;
     ata->regs.ctrl  = 0x0001;
     ata->regs.stat  = (DEV_ID << 28) | (REV << 24);
     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.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.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.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.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.dtr1  = (DMA_MODE0_TEOC << ATA_TEOC) | (DMA_MODE0_TD << ATA_TD) | (DMA_MODE0_TM << ATA_TM);
     ata->regs.txb   = 0;
     ata->regs.txb   = 0;
 
 
     // copy the config settings
     // copy the config settings
     ata->ata_number = i;
     ata->ata_number = i;
     ata->irq        = config.atas[i].irq;
     ata->irq        = config.atas[i].irq;
     ata->baseaddr   = config.atas[i].baseaddr;
     ata->baseaddr   = config.atas[i].baseaddr;
 
 
     ata->devices.device0.size   = config.atas[i].dev_size0;
     ata->devices.device0.size   = config.atas[i].dev_size0;
     ata->devices.device0.type   = config.atas[i].dev_type0;
     ata->devices.device0.type   = config.atas[i].dev_type0;
     ata->devices.device0.packet = config.atas[i].dev_packet0;
     ata->devices.device0.packet = config.atas[i].dev_packet0;
     ata->devices.device1.size   = config.atas[i].dev_size1;
     ata->devices.device1.size   = config.atas[i].dev_size1;
     ata->devices.device1.type   = config.atas[i].dev_type1;
     ata->devices.device1.type   = config.atas[i].dev_type1;
     ata->devices.device1.packet = config.atas[i].dev_packet1;
     ata->devices.device1.packet = config.atas[i].dev_packet1;
 
 
     // inform simulator about new read/write delay timings
     // 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) );
     adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) );
 
 
     /* initialize simulator & ata_devices                                */
     /* initialize simulator & ata_devices                                */
     if (!first_time)
     if (!first_time)
     {
     {
       /* Connect ata_devices.                                            */
       /* Connect ata_devices.                                            */
       ata_devices_init(&ata->devices, config.atas[i].dev_file0, config.atas[i].dev_file1);
       ata_devices_init(&ata->devices, config.atas[i].dev_file0, config.atas[i].dev_file1);
 
 
       register_memoryarea(ata->baseaddr, ATA_ADDR_SPACE, 4, 0, ata_read32, ata_write32);
       register_memoryarea(ata->baseaddr, ATA_ADDR_SPACE, 4, 0, ata_read32, ata_write32);
     }
     }
 
 
     /* the reset bit in the control register 'ctrl' is set, reset connect ata-devices */
     /* the reset bit in the control register 'ctrl' is set, reset connect ata-devices */
     ata_devices_hw_reset(&ata->devices, 1);
     ata_devices_hw_reset(&ata->devices, 1);
   }
   }
 
 
   first_time++;
   first_time++;
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
 
 
/* Convert a memory address to a device struct and relative address.
/* Convert a memory address to a device struct and relative address.
 * Return nonzero on success */
 * Return nonzero on success */
int ata_find_device( unsigned long addr, ata_host **ata, unsigned long *reladdr )
int ata_find_device( unsigned long addr, ata_host **ata, unsigned long *reladdr )
{
{
  unsigned i;
  unsigned i;
  *ata = NULL;
  *ata = NULL;
 
 
  for ( i = 0; i < config.natas && *ata == NULL; ++ i ) {
  for ( i = 0; i < config.natas && *ata == NULL; ++ i ) {
    if ( (addr >= atas[i].baseaddr) && (addr < atas[i].baseaddr + ATA_ADDR_SPACE) )
    if ( (addr >= atas[i].baseaddr) && (addr < atas[i].baseaddr + ATA_ADDR_SPACE) )
      *ata = &(atas[i]);
      *ata = &(atas[i]);
  }
  }
 
 
  /* verify we found a device */
  /* verify we found a device */
  if ( *ata == NULL )
  if ( *ata == NULL )
    return 0;
    return 0;
 
 
  /* Verify legal address */
  /* Verify legal address */
  if ( (addr - (*ata)->baseaddr) % 4 != 0 )
  if ( (addr - (*ata)->baseaddr) % 4 != 0 )
    return 0;
    return 0;
 
 
  *reladdr = addr - (*ata) -> baseaddr;
  *reladdr = addr - (*ata) -> baseaddr;
  return 1;
  return 1;
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
 
 
/*
/*
  Read a register
  Read a register
*/
*/
unsigned long ata_read32( unsigned long addr )
unsigned long ata_read32( unsigned long addr )
{
{
    ata_host *ata;
    ata_host *ata;
 
 
    if ( !ata_find_device( addr, &ata, &addr ) )    {
    if ( !ata_find_device( addr, &ata, &addr ) )    {
        fprintf(stderr, "ata_read32( 0x%08lX ): Not in registered range(s)\n", addr );
        fprintf(stderr, "ata_read32( 0x%08lX ): Not in registered range(s)\n", addr );
        return 0;
        return 0;
    }
    }
 
 
    /* determine if ata_host or ata_device addressed */
    /* determine if ata_host or ata_device addressed */
    if (is_ata_hostadr(addr))
    if (is_ata_hostadr(addr))
    {
    {
        // Accesses to internal register take 2cycles
        // Accesses to internal register take 2cycles
        adjust_rw_delay( ata->baseaddr, 2, 2 );
        adjust_rw_delay( ata->baseaddr, 2, 2 );
 
 
        switch( addr ) {
        switch( addr ) {
            case ATA_CTRL :
            case ATA_CTRL :
                return ata -> regs.ctrl;
                return ata -> regs.ctrl;
 
 
            case ATA_STAT :
            case ATA_STAT :
                return ata -> regs.stat;
                return ata -> regs.stat;
 
 
            case ATA_PCTR :
            case ATA_PCTR :
                return ata -> regs.pctr;
                return ata -> regs.pctr;
 
 
#if (DEV_ID > 1)
#if (DEV_ID > 1)
            case ATA_PFTR0:
            case ATA_PFTR0:
                return ata -> regs.pftr0;
                return ata -> regs.pftr0;
 
 
            case ATA_PFTR1:
            case ATA_PFTR1:
                return ata -> regs.pftr1;
                return ata -> regs.pftr1;
#endif
#endif
 
 
#if (DEV_ID > 2)
#if (DEV_ID > 2)
            case ATA_DTR0 :
            case ATA_DTR0 :
                return ata -> regs.dtr0;
                return ata -> regs.dtr0;
 
 
            case ATA_DTR1 :
            case ATA_DTR1 :
                return ata -> regs.dtr1;
                return ata -> regs.dtr1;
 
 
            case ATA_RXB  :
            case ATA_RXB  :
                return ata -> regs.rxb;
                return ata -> regs.rxb;
#endif
#endif
 
 
            default:
            default:
                return 0;
                return 0;
        }
        }
    }
    }
    else
    else
    {
    {
        // make sure simulator uses correct read/write delay timings
        // make sure simulator uses correct read/write delay timings
#if (DEV_ID > 1)
#if (DEV_ID > 1)
        if ( (addr & 0x7f) == ATA_DR)
        if ( (addr & 0x7f) == ATA_DR)
        {
        {
          if (ata->devices.dev)
          if (ata->devices.dev)
              adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) );
              adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) );
          else
          else
              adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) );
              adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) );
        }
        }
        else
        else
#endif
#endif
        adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) );
        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);
        return ata_devices_read(&ata->devices, addr & 0x7f);
    }
    }
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
 
 
/*
/*
  Write a register
  Write a register
*/
*/
void ata_write32( unsigned long addr, unsigned long value )
void ata_write32( unsigned long addr, unsigned long value )
{
{
    ata_host *ata;
    ata_host *ata;
 
 
    if ( !ata_find_device( addr, &ata, &addr ) )
    if ( !ata_find_device( addr, &ata, &addr ) )
    {
    {
        fprintf(stderr, "ata_write32( 0x%08lX ): Not in registered range(s)\n", addr );
        fprintf(stderr, "ata_write32( 0x%08lX ): Not in registered range(s)\n", addr );
        return;
        return;
    }
    }
 
 
    /* determine if ata_host or ata_device addressed */
    /* determine if ata_host or ata_device addressed */
    if (is_ata_hostadr(addr))
    if (is_ata_hostadr(addr))
    {
    {
       // Accesses to internal register take 2cycles
       // Accesses to internal register take 2cycles
       adjust_rw_delay( ata->baseaddr, 2, 2 );
       adjust_rw_delay( ata->baseaddr, 2, 2 );
 
 
        switch( addr ) {
        switch( addr ) {
            case ATA_CTRL :
            case ATA_CTRL :
                ata -> regs.ctrl =  value;
                ata -> regs.ctrl =  value;
 
 
                /* check if reset bit set, if so reset ata-devices    */
                /* check if reset bit set, if so reset ata-devices    */
                if (value & ATA_RST)
                if (value & ATA_RST)
                  ata_devices_hw_reset(&ata->devices, 1);
                  ata_devices_hw_reset(&ata->devices, 1);
                else
                else
                  ata_devices_hw_reset(&ata->devices, 0);
                  ata_devices_hw_reset(&ata->devices, 0);
                break;
                break;
 
 
            case ATA_STAT :
            case ATA_STAT :
                ata -> regs.stat = (ata -> regs.stat & ~ATA_IDEIS) | (ata -> regs.stat & ATA_IDEIS & value);
                ata -> regs.stat = (ata -> regs.stat & ~ATA_IDEIS) | (ata -> regs.stat & ATA_IDEIS & value);
                break;
                break;
 
 
            case ATA_PCTR :
            case ATA_PCTR :
                ata -> regs.pctr = value;
                ata -> regs.pctr = value;
                break;
                break;
 
 
            case ATA_PFTR0:
            case ATA_PFTR0:
                ata -> regs.pftr0 = value;
                ata -> regs.pftr0 = value;
                break;
                break;
 
 
            case ATA_PFTR1:
            case ATA_PFTR1:
                ata -> regs.pftr1 = value;
                ata -> regs.pftr1 = value;
                break;
                break;
 
 
            case ATA_DTR0 :
            case ATA_DTR0 :
                ata -> regs.dtr0  = value;
                ata -> regs.dtr0  = value;
                break;
                break;
 
 
            case ATA_DTR1 :
            case ATA_DTR1 :
                ata -> regs.dtr1  = value;
                ata -> regs.dtr1  = value;
                break;
                break;
 
 
            case ATA_TXB  :
            case ATA_TXB  :
                ata -> regs.txb   = value;
                ata -> regs.txb   = value;
                break;
                break;
 
 
            default:
            default:
                /* ERROR-macro currently only supports simple strings. */
                /* ERROR-macro currently only supports simple strings. */
                /*
                /*
                  fprintf(stderr, "ERROR  : Unknown register for OCIDEC(%1d).\n", DEV_ID );
                  fprintf(stderr, "ERROR  : Unknown register for OCIDEC(%1d).\n", DEV_ID );
 
 
                  Tried to show some useful info here.
                  Tried to show some useful info here.
                  But when using 'DM'-simulator-command, the screen gets filled with these messages.
                  But when using 'DM'-simulator-command, the screen gets filled with these messages.
                  Thereby eradicating the usefulness of the message
                  Thereby eradicating the usefulness of the message
                */
                */
                break;
                break;
        }
        }
    }
    }
    else
    else
    {
    {
        // make sure simulator uses correct read/write delay timings
        // make sure simulator uses correct read/write delay timings
#if (DEV_ID > 1)
#if (DEV_ID > 1)
        if ( (addr & 0x7f) == ATA_DR)
        if ( (addr & 0x7f) == ATA_DR)
        {
        {
          if (ata->devices.dev)
          if (ata->devices.dev)
              adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) );
              adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr1), ata_pio_delay(ata->regs.ftcr1) );
          else
          else
              adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) );
              adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.ftcr0), ata_pio_delay(ata->regs.ftcr0) );
        }
        }
        else
        else
#endif
#endif
        adjust_rw_delay( ata->baseaddr, ata_pio_delay(ata->regs.pctr), ata_pio_delay(ata->regs.pctr) );
        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);
        ata_devices_write(&ata->devices, addr & 0x7f, value);
    }
    }
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 
 
 
/* Dump status */
/* Dump status */
void ata_status( void )
void ata_status( void )
{
{
  unsigned i;
  unsigned i;
  ata_host *ata;
  ata_host *ata;
 
 
  for ( i = 0; i < config.natas; i++ ) {
  for ( i = 0; i < config.natas; i++ ) {
      ata = &(atas[i]);
      ata = &(atas[i]);
 
 
      if ( ata->baseaddr == 0 )
      if ( ata->baseaddr == 0 )
         continue;
         continue;
 
 
       printf( "\nOCIDEC-%1d %u at: 0x%08X\n", DEV_ID, i, ata->baseaddr );
       PRINTF( "\nOCIDEC-%1d %u at: 0x%08X\n", DEV_ID, i, ata->baseaddr );
       printf( "ATA CTRL     : 0x%08lX\n", ata->regs.ctrl  );
       PRINTF( "ATA CTRL     : 0x%08lX\n", ata->regs.ctrl  );
       printf( "ATA STAT     : 0x%08lx\n", ata->regs.stat  );
       PRINTF( "ATA STAT     : 0x%08lx\n", ata->regs.stat  );
       printf( "ATA PCTR     : 0x%08lx\n", ata->regs.pctr  );
       PRINTF( "ATA PCTR     : 0x%08lx\n", ata->regs.pctr  );
 
 
#if (DEV_ID > 1)
#if (DEV_ID > 1)
       printf( "ATA FCTR0    : 0x%08lx\n", ata->regs.pftr0 );
       PRINTF( "ATA FCTR0    : 0x%08lx\n", ata->regs.pftr0 );
       printf( "ATA FCTR1    : 0x%08lx\n", ata->regs.pftr1 );
       PRINTF( "ATA FCTR1    : 0x%08lx\n", ata->regs.pftr1 );
#endif
#endif
 
 
#if (DEV_ID > 2)
#if (DEV_ID > 2)
       printf( "ATA DTR0     : 0x%08lx\n", ata->regs.dtr0  );
       PRINTF( "ATA DTR0     : 0x%08lx\n", ata->regs.dtr0  );
       printf( "ATA DTR1     : 0x%08lx\n", ata->regs.dtr1  );
       PRINTF( "ATA DTR1     : 0x%08lx\n", ata->regs.dtr1  );
       printf( "ATA TXD      : 0x%08lx\n", ata->regs.txb   );
       PRINTF( "ATA TXD      : 0x%08lx\n", ata->regs.txb   );
       printf( "ATA RXD      : 0x%08lx\n", ata->regs.rxb   );
       PRINTF( "ATA RXD      : 0x%08lx\n", ata->regs.rxb   );
#endif
#endif
  }
  }
}
}
/* ========================================================================= */
/* ========================================================================= */
 
 

powered by: WebSVN 2.1.0

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