URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [or1ksim/] [peripheral/] [atahost.c] - Rev 1358
Go to most recent revision | Compare with Previous | Blame | View Log
/* 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 "config.h" #ifdef HAVE_INTTYPES_H #include <inttypes.h> #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" static ata_host atas[MAX_ATAS]; /* reset and initialize ATA host core(s) */ void ata_reset(void) { static int first_time=0; unsigned i; ata_host *ata; // for all ATA cores for (i=0; i < config.natas; i++) { ata = &(atas[i]); // 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; // copy the config settings ata->ata_number = i; ata->irq = config.atas[i].irq; ata->baseaddr = config.atas[i].baseaddr; ata->devices.device0.size = config.atas[i].dev_size0; ata->devices.device0.type = config.atas[i].dev_type0; ata->devices.device0.packet = config.atas[i].dev_packet0; ata->devices.device1.size = config.atas[i].dev_size1; ata->devices.device1.type = config.atas[i].dev_type1; ata->devices.device1.packet = config.atas[i].dev_packet1; // 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) ); /* initialize simulator & ata_devices */ if (!first_time) { /* Connect ata_devices. */ 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); } /* the reset bit in the control register 'ctrl' is set, reset connect ata-devices */ ata_devices_hw_reset(&ata->devices, 1); } first_time++; } /* ========================================================================= */ /* Convert a memory address to a device struct and relative address. * Return nonzero on success */ int ata_find_device( oraddr_t addr, ata_host **ata, oraddr_t *reladdr ) { unsigned i; *ata = NULL; for ( i = 0; i < config.natas && *ata == NULL; ++ i ) { if ( (addr >= atas[i].baseaddr) && (addr < atas[i].baseaddr + ATA_ADDR_SPACE) ) *ata = &(atas[i]); } /* verify we found a device */ if ( *ata == NULL ) return 0; /* Verify legal address */ if ( (addr - (*ata)->baseaddr) % 4 != 0 ) return 0; *reladdr = addr - (*ata) -> baseaddr; return 1; } /* ========================================================================= */ /* Read a register */ uint32_t ata_read32( oraddr_t addr ) { ata_host *ata; if ( !ata_find_device( addr, &ata, &addr ) ) { fprintf(stderr, "ata_read32( 0x%"PRIxADDR" ): Not in registered range(s)\n", addr ); return 0; } /* 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 ) { ata_host *ata; if ( !ata_find_device( addr, &ata, &addr ) ) { fprintf(stderr, "ata_write32( 0x%"PRIxADDR" ): Not in registered range(s)\n", addr ); return; } /* 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 ) { unsigned i; ata_host *ata; for ( i = 0; i < config.natas; i++ ) { ata = &(atas[i]); if ( ata->baseaddr == 0 ) continue; PRINTF( "\nOCIDEC-%1d %u at: 0x%"PRIxADDR"\n", DEV_ID, i, 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_natas(union param_val val, void *dat) { if (val.int_val >= 0 && val.int_val < MAX_ATAS) config.natas = val.int_val; else CONFIG_ERROR("invalid number of devices."); } void ata_baseaddr(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.natas) config.atas[current_device].baseaddr = val.addr_val; else CONFIG_ERROR("invalid device number."); } void ata_irq(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.natas) config.atas[current_device].irq = val.int_val; else CONFIG_ERROR("invalid device number."); } void ata_dev_type0(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.natas) config.atas[current_device].dev_type0 = val.int_val; else CONFIG_ERROR("invalid device number."); } void ata_dev_file0(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.natas) strcpy (config.atas[current_device].dev_file0, val.str_val); else CONFIG_ERROR("invalid device number."); } void ata_dev_size0(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.natas) config.atas[current_device].dev_size0 = val.int_val; else CONFIG_ERROR("invalid device number."); } void ata_dev_packet0(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.natas) config.atas[current_device].dev_packet0 = val.int_val; else CONFIG_ERROR("invalid device number."); } void ata_dev_type1(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.natas) config.atas[current_device].dev_type1 = val.int_val; else CONFIG_ERROR("invalid device number."); } void ata_dev_file1(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.natas) strcpy (config.atas[current_device].dev_file1, val.str_val); else CONFIG_ERROR("invalid device number."); } void ata_dev_size1(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.natas) config.atas[current_device].dev_size1 = val.int_val; else CONFIG_ERROR("invalid device number."); } void ata_dev_packet1(union param_val val, void *dat) { if (current_device >= 0 && current_device < config.natas) config.atas[current_device].dev_packet1 = val.int_val; else CONFIG_ERROR("invalid device number."); } void reg_ata_sec(void) { struct config_section *sec = reg_config_sec("ata", NULL, NULL); reg_config_param(sec, "natas", paramt_int, ata_natas); reg_config_param(sec, "device", paramt_int, change_device); 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); reg_config_param(sec, "enddevice", paramt_none, end_device); }
Go to most recent revision | Compare with Previous | Blame | View Log