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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc3/] [or1ksim/] [peripheral/] [atadevice.c] - Diff between revs 1350 and 1364

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

Rev 1350 Rev 1364
/*
/*
    atadevice.c -- ATA Device simulation
    atadevice.c -- ATA Device simulation
    Simulates a harddisk, using a local streams.
    Simulates a harddisk, using a local streams.
    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.
*/
*/
 
 
#include <string.h>
#include <string.h>
#include <stdarg.h>
#include <stdarg.h>
 
 
#include "config.h"
#include "config.h"
 
 
#ifdef HAVE_INTTYPES_H
#ifdef HAVE_INTTYPES_H
#include <inttypes.h>
#include <inttypes.h>
#endif
#endif
 
 
#include "port.h"
#include "port.h"
#include "arch.h"
#include "arch.h"
#include "abstract.h"
#include "abstract.h"
#include "sched.h"
#include "sched.h"
 
 
#include "messages.h"
#include "messages.h"
#include "atadevice.h"
#include "atadevice.h"
#include "atacmd.h"
#include "atacmd.h"
#include "sim-config.h"
#include "sim-config.h"
#include "atadevice_cmdi.h"
#include "atadevice_cmdi.h"
 
 
/*
/*
 mandatory commands:
 mandatory commands:
 - execute device diagnostics       (done)
 - execute device diagnostics       (done)
 - flush cache
 - flush cache
 - identify device                  (done)
 - identify device                  (done)
 - initialize device parameters     (done)
 - initialize device parameters     (done)
 - read dma
 - read dma
 - read multiple
 - read multiple
 - read sector(s)                   (done)
 - read sector(s)                   (done)
 - read verify sector(s)
 - read verify sector(s)
 - seek
 - seek
 - set features
 - set features
 - set multiple mode
 - set multiple mode
 - write dma
 - write dma
 - write multiple
 - write multiple
 - write sector(s)
 - write sector(s)
 
 
 
 
 optional commands:
 optional commands:
 - download microcode
 - download microcode
 - nop
 - nop
 - read buffer
 - read buffer
 - write buffer
 - write buffer
 
 
 
 
 prohibited commands:
 prohibited commands:
 - device reset
 - device reset
*/
*/
 
 
 
 
/*
/*
  D E V I C E S _ I N I T
  D E V I C E S _ I N I T
*/
*/
void ata_devices_init(ata_devices *devices, const char *filename0, const char *filename1)
void ata_devices_init(ata_devices *devices)
{
{
  ata_device_init(&devices->device0, 0, filename0);
  ata_device_init(&devices->device0, 0);
 
 
  if (devices->device0.type)
  if (devices->device0.type)
    ata_device_init(&devices->device1, ATA_DHR_DEV, filename1);
    ata_device_init(&devices->device1, ATA_DHR_DEV);
  else
  else
    ata_device_init(&devices->device1,           0, filename1);
    ata_device_init(&devices->device1,           0);
}
}
 
 
 
 
void ata_device_init(ata_device *device, int dev, const char *filename)
void ata_device_init(ata_device *device, int dev)
{
{
  /* set DeviceID                                                     */
  /* set DeviceID                                                     */
  device->internals.dev = dev;
  device->internals.dev = dev;
 
 
  /* generate stream for hd_simulation                                */
  /* generate stream for hd_simulation                                */
  switch(device->type)
  switch(device->type)
  {
  {
    case TYPE_NO_CONNECT:
    case TYPE_NO_CONNECT:
      MSG_NOTE("ata_device, using type NO_CONNECT.");
      MSG_NOTE("ata_device, using type NO_CONNECT.");
      device->stream = NULL;
      device->stream = NULL;
      break;
      break;
 
 
    case TYPE_FILE:
    case TYPE_FILE:
      MSG_NOTE("ata_device, using device type FILE.");
      MSG_NOTE("ata_device, using device type FILE.");
      device->stream = open_file(&device->size, filename);
      device->stream = open_file(&device->size, device->file);
      break;
      break;
 
 
    case TYPE_LOCAL:
    case TYPE_LOCAL:
      MSG_NOTE("ata_device, using device type LOCAL.");
      MSG_NOTE("ata_device, using device type LOCAL.");
      device->stream = open_local();
      device->stream = open_local();
      break;
      break;
 
 
    default:
    default:
      MSG_FATAL("ata_device, illegal device-type.");
      MSG_FATAL("ata_device, illegal device-type.");
      MSG_EMPTY("defaulting to type NO_CONNECT.");
      MSG_EMPTY("defaulting to type NO_CONNECT.");
      device->stream = NULL;
      device->stream = NULL;
      break;
      break;
  }
  }
}
}
 
 
/* Use a file to simulate a hard-disk                                 */
/* Use a file to simulate a hard-disk                                 */
FILE *open_file(unsigned long *size, const char *filename)
FILE *open_file(unsigned long *size, const char *filename)
{
{
   FILE *fp;
   FILE *fp;
   unsigned long  n;
   unsigned long  n;
 
 
   // TODO:
   // TODO:
 
 
   /* check if a file with name 'filename' already exists             */
   /* check if a file with name 'filename' already exists             */
   if ( !(fp = fopen(filename, "rb+")) )
   if ( !(fp = fopen(filename, "rb+")) )
     if ( !(fp = fopen(filename, "wb+")) )
     if ( !(fp = fopen(filename, "wb+")) )
     {
     {
       MSG_FATAL( strcat("ata_open_file, cannot open hd-file ", filename) );
       MSG_FATAL( strcat("ata_open_file, cannot open hd-file ", filename) );
       return NULL;
       return NULL;
     }
     }
     else
     else
     {
     {
       /* TODO create a file 'size' large */
       /* TODO create a file 'size' large */
       /* create a file 'size' large                                  */
       /* create a file 'size' large                                  */
       MSG_NOTE("ata_device; generating a new hard disk file.");
       MSG_NOTE("ata_device; generating a new hard disk file.");
       MSG_EMPTY("This may take a while, depending on the requested size.");
       MSG_EMPTY("This may take a while, depending on the requested size.");
       for (n=0; n < (*size << 20); n++)
       for (n=0; n < (*size << 20); n++)
         fputc(0, fp);
         fputc(0, fp);
     }
     }
   else /* file already exist                                         */
   else /* file already exist                                         */
     fprintf(stderr, "file %s already exists. Using existing file.\n", filename);
     fprintf(stderr, "file %s already exists. Using existing file.\n", filename);
 
 
 
 
   ata_device_debug(1, "requested filesize was: %d (MBytes).\n", *size);
   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*/
   /* get the size of the file. This is also the size of the harddisk*/
   fseek(fp, 0, SEEK_END);
   fseek(fp, 0, SEEK_END);
   *size = ftell(fp);
   *size = ftell(fp);
 
 
   ata_device_debug(1, "actual filesize is: %d (MBytes).\n", *size >> 20);
   ata_device_debug(1, "actual filesize is: %d (MBytes).\n", *size >> 20);
 
 
   return fp;
   return fp;
}
}
 
 
 
 
/* Use a the local filesystem as a hard-disk                          */
/* Use a the local filesystem as a hard-disk                          */
FILE *open_local(void)
FILE *open_local(void)
{
{
 // TODO:
 // TODO:
 MSG_WARNING("ata_device; device type LOCAL is not supported yet.");
 MSG_WARNING("ata_device; device type LOCAL is not supported yet.");
 MSG_EMPTY("defaulting to device type NO_CONNECT.");
 MSG_EMPTY("defaulting to device type NO_CONNECT.");
 return NULL;
 return NULL;
}
}
 
 
 
 
 
 
 
 
/*
/*
  D E V I C E S _ H W _ R E S E T
  D E V I C E S _ H W _ R E S E T
*/
*/
/* power-on and hardware reset                                        */
/* power-on and hardware reset                                        */
void ata_devices_hw_reset(ata_devices *devices, int reset_signal)
void ata_devices_hw_reset(ata_devices *devices, int reset_signal)
{
{
  /* display debug information                                        */
  /* display debug information                                        */
  ata_device_debug(2, "ata_devices_hw_reset.\n");
  ata_device_debug(2, "ata_devices_hw_reset.\n");
 
 
  /* find device 0                                                    */
  /* find device 0                                                    */
  if ( (devices->device0.stream) && (devices->device1.stream) )
  if ( (devices->device0.stream) && (devices->device1.stream) )
  {
  {
    /* this one is simple, device0 is device0                         */
    /* this one is simple, device0 is device0                         */
 
 
    /* 1) handle device1 first                                        */
    /* 1) handle device1 first                                        */
    ata_device_hw_reset(&devices->device1, reset_signal,
    ata_device_hw_reset(&devices->device1, reset_signal,
                        1,   /* assert dasp, this is device1          */
                        1,   /* assert dasp, this is device1          */
                        0,   /* negate pdiag input, no more devices   */
                        0,   /* negate pdiag input, no more devices   */
                        0);  /* negate dasp input, no more devices    */
                        0);  /* negate dasp input, no more devices    */
 
 
    /* 2) Then handle device0                                         */
    /* 2) Then handle device0                                         */
    ata_device_hw_reset(&devices->device0, reset_signal,
    ata_device_hw_reset(&devices->device0, reset_signal,
                        0,
                        0,
                        devices->device1.sigs.pdiago,
                        devices->device1.sigs.pdiago,
                        devices->device1.sigs.daspo);
                        devices->device1.sigs.daspo);
  }
  }
  else if (devices->device0.stream)
  else if (devices->device0.stream)
  {
  {
    /* device0 is device0, there's no device1                         */
    /* device0 is device0, there's no device1                         */
    ata_device_hw_reset(&devices->device0, reset_signal,
    ata_device_hw_reset(&devices->device0, reset_signal,
                        0,   /* negate dasp, this is device0          */
                        0,   /* negate dasp, this is device0          */
                        0,   /* negate pdiag input, there's no device1*/
                        0,   /* negate pdiag input, there's no device1*/
                        0);  /* negate dasp input, there's no device1 */
                        0);  /* negate dasp input, there's no device1 */
  }
  }
  else if (devices->device1.stream)
  else if (devices->device1.stream)
  {
  {
    /* device1 is (logical) device0, there's no (physical) device0    */
    /* device1 is (logical) device0, there's no (physical) device0    */
    ata_device_hw_reset(&devices->device1, reset_signal,
    ata_device_hw_reset(&devices->device1, reset_signal,
                        0,   /* negate dasp, this is device0          */
                        0,   /* negate dasp, this is device0          */
                        0,   /* negate pdiag input, there's no device1*/
                        0,   /* negate pdiag input, there's no device1*/
                        0);  /* negate dasp input, there's no device1 */
                        0);  /* negate dasp input, there's no device1 */
  }
  }
  else
  else
  {
  {
    /* no devices connected                                           */
    /* no devices connected                                           */
    ata_device_debug(1, "ata_device_hw_reset, no devices connected.\n");
    ata_device_debug(1, "ata_device_hw_reset, no devices connected.\n");
  }
  }
}
}
 
 
void ata_device_hw_reset(ata_device *device, int reset_signal,
void ata_device_hw_reset(ata_device *device, int reset_signal,
  int daspo, int pdiagi, int daspi)
  int daspo, int pdiagi, int daspi)
{
{
    /* check ata-device state                                         */
    /* check ata-device state                                         */
    if (device->internals.state == ATA_STATE_HW_RST)
    if (device->internals.state == ATA_STATE_HW_RST)
    {
    {
      if (!reset_signal)
      if (!reset_signal)
      {
      {
        /* hardware reset finished                                    */
        /* hardware reset finished                                    */
 
 
        /* set sectors_per_track & heads_per_cylinders                */
        /* set sectors_per_track & heads_per_cylinders                */
        device->internals.sectors_per_track = SECTORS;
        device->internals.sectors_per_track = SECTORS;
        device->internals.heads_per_cylinder = HEADS;
        device->internals.heads_per_cylinder = HEADS;
 
 
        /* set device1 input signals                                  */
        /* set device1 input signals                                  */
        device->sigs.pdiagi = pdiagi;
        device->sigs.pdiagi = pdiagi;
        device->sigs.daspi  = daspi;
        device->sigs.daspi  = daspi;
 
 
        ata_execute_device_diagnostics_cmd(device);
        ata_execute_device_diagnostics_cmd(device);
 
 
        /* clear busy bit                                             */
        /* clear busy bit                                             */
        device->regs.status &= ~ATA_SR_BSY;
        device->regs.status &= ~ATA_SR_BSY;
 
 
        /* set DRDY bit, when not a PACKET device                     */
        /* set DRDY bit, when not a PACKET device                     */
        if (!device->packet)
        if (!device->packet)
            device->regs.status |= ATA_SR_DRDY;
            device->regs.status |= ATA_SR_DRDY;
 
 
        /* set new state                                              */
        /* set new state                                              */
        device->internals.state = ATA_STATE_IDLE;
        device->internals.state = ATA_STATE_IDLE;
      }
      }
    }
    }
    else
    else
      if (reset_signal)
      if (reset_signal)
      {
      {
        /* hardware reset signal asserted, stop what we are doing     */
        /* hardware reset signal asserted, stop what we are doing     */
 
 
        /* negate bus signals                                         */
        /* negate bus signals                                         */
        device->sigs.iordy  = 0;
        device->sigs.iordy  = 0;
        device->sigs.intrq  = 0;
        device->sigs.intrq  = 0;
        device->sigs.dmarq  = 0;
        device->sigs.dmarq  = 0;
        device->sigs.pdiago = 0;
        device->sigs.pdiago = 0;
        device->sigs.daspo  = daspo;
        device->sigs.daspo  = daspo;
 
 
        /* set busy bit                                               */
        /* set busy bit                                               */
        device->regs.status |= ATA_SR_BSY;
        device->regs.status |= ATA_SR_BSY;
        PRINTF("setting status register BSY 0x%2X\n", device->regs.status);
        PRINTF("setting status register BSY 0x%2X\n", device->regs.status);
 
 
        /* set new state                                              */
        /* set new state                                              */
        device->internals.state = ATA_STATE_HW_RST;
        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
  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
  Handles - software reset
          - Interrupt enable bit
          - Interrupt enable bit
*/
*/
void ata_device_do_control_register(ata_device *device)
void ata_device_do_control_register(ata_device *device)
{
{
    /* TODO respond to new values of nIEN */
    /* TODO respond to new values of nIEN */
    /* if device not selected, respond to new values of nIEN & SRST */
    /* if device not selected, respond to new values of nIEN & SRST */
 
 
  /* check if SRST bit is set                                         */
  /* check if SRST bit is set                                         */
  if (device->regs.device_control & ATA_DCR_RST)
  if (device->regs.device_control & ATA_DCR_RST)
  {
  {
    if (device->internals.state == ATA_STATE_IDLE)
    if (device->internals.state == ATA_STATE_IDLE)
    {   /* start software reset                                       */
    {   /* start software reset                                       */
        /* negate bus signals                                         */
        /* negate bus signals                                         */
        device->sigs.pdiago = 0;
        device->sigs.pdiago = 0;
        device->sigs.intrq  = 0;
        device->sigs.intrq  = 0;
        device->sigs.iordy  = 0;
        device->sigs.iordy  = 0;
        device->sigs.dmarq  = 0;
        device->sigs.dmarq  = 0;
 
 
        /* set busy bit                                               */
        /* set busy bit                                               */
        device->regs.status |= ATA_SR_BSY;
        device->regs.status |= ATA_SR_BSY;
 
 
        /* set new state                                              */
        /* set new state                                              */
        device->internals.state = ATA_STATE_SW_RST;
        device->internals.state = ATA_STATE_SW_RST;
 
 
        /* display debug information                                  */
        /* display debug information                                  */
        ata_device_debug(2, "ata_device_sw_reset initiated.\n");
        ata_device_debug(2, "ata_device_sw_reset initiated.\n");
    }
    }
  }
  }
  else if (device->internals.state == ATA_STATE_SW_RST)
  else if (device->internals.state == ATA_STATE_SW_RST)
  {   /* are we doing a software reset ??                             */
  {   /* are we doing a software reset ??                             */
      /* SRST bit cleared, end of software reset                      */
      /* SRST bit cleared, end of software reset                      */
 
 
      /*execute device diagnostics                                    */
      /*execute device diagnostics                                    */
      ata_execute_device_diagnostics_cmd(device);
      ata_execute_device_diagnostics_cmd(device);
 
 
      /* clear busy bit                                               */
      /* clear busy bit                                               */
      device->regs.status &= ~ATA_SR_BSY;
      device->regs.status &= ~ATA_SR_BSY;
 
 
      /* set DRDY bit, when not a PACKET device                       */
      /* set DRDY bit, when not a PACKET device                       */
      if (!device->packet)
      if (!device->packet)
        device->regs.status |= ATA_SR_DRDY;
        device->regs.status |= ATA_SR_DRDY;
 
 
      /* set new state                                                */
      /* set new state                                                */
      device->internals.state = ATA_STATE_IDLE;
      device->internals.state = ATA_STATE_IDLE;
 
 
      /* display debug information                                    */
      /* display debug information                                    */
      ata_device_debug(2, "ata_device_sw_reset done.\n");
      ata_device_debug(2, "ata_device_sw_reset done.\n");
  }
  }
  /*
  /*
  <else> We are doing a hardware reset (or similar)
  <else> We are doing a hardware reset (or similar)
         ignore command
         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
  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)
void ata_device_do_command_register(ata_device *device)
{
{
  /* check BSY & DRQ                                                  */
  /* check BSY & DRQ                                                  */
  if ( (device->regs.status & ATA_SR_BSY) || (device->regs.status & ATA_SR_DRQ) )
  if ( (device->regs.status & ATA_SR_BSY) || (device->regs.status & ATA_SR_DRQ) )
     if (device->regs.command != DEVICE_RESET)
     if (device->regs.command != DEVICE_RESET)
        MSG_WARNING("ata_device_write, writing a command while BSY or DRQ asserted.");
        MSG_WARNING("ata_device_write, writing a command while BSY or DRQ asserted.");
 
 
  /* check if device selected                                         */
  /* check if device selected                                         */
  if ( (device->regs.device_head & ATA_DHR_DEV) == device->internals.dev )
  if ( (device->regs.device_head & ATA_DHR_DEV) == device->internals.dev )
      ata_device_execute_cmd(device);
      ata_device_execute_cmd(device);
  else
  else
  {
  {
      /* if not selected, only respond to EXECUTE DEVICE DIAGNOSTICS  */
      /* if not selected, only respond to EXECUTE DEVICE DIAGNOSTICS  */
      if (device->regs.command == EXECUTE_DEVICE_DIAGNOSTICS)
      if (device->regs.command == EXECUTE_DEVICE_DIAGNOSTICS)
          ata_device_execute_cmd(device);
          ata_device_execute_cmd(device);
  }
  }
}
}
 
 
 
 
/*
/*
  D E V I C E S _ R E A D
  D E V I C E S _ R E A D
*/
*/
/* Read from devices                                                  */
/* Read from devices                                                  */
short ata_devices_read(ata_devices *devices, char adr)
short ata_devices_read(ata_devices *devices, char adr)
{
{
    ata_device *device;
    ata_device *device;
 
 
    /* check for no connected devices                                 */
    /* check for no connected devices                                 */
    if ( (!devices->device0.stream) && (!devices->device1.stream) )
    if ( (!devices->device0.stream) && (!devices->device1.stream) )
        MSG_ERROR("ata_devices_read, no ata devices connected.");
        MSG_ERROR("ata_devices_read, no ata devices connected.");
    else
    else
    {
    {
      /* check if both device0 and device1 are connected              */
      /* check if both device0 and device1 are connected              */
      if ( (devices->device0.stream) && (devices->device1.stream) )
      if ( (devices->device0.stream) && (devices->device1.stream) )
      {
      {
          /* get the current active device                            */
          /* get the current active device                            */
          if (devices->device1.regs.device_head & ATA_DHR_DEV)
          if (devices->device1.regs.device_head & ATA_DHR_DEV)
              device = &devices->device1;
              device = &devices->device1;
          else
          else
              device = &devices->device0;
              device = &devices->device0;
      }
      }
      else
      else
      {
      {
          /* only one device connected                                */
          /* only one device connected                                */
          if (devices->device1.stream)
          if (devices->device1.stream)
              device = &devices->device1;
              device = &devices->device1;
          else
          else
              device = &devices->device0;
              device = &devices->device0;
      }
      }
 
 
      /* return data provided by selected device                      */
      /* return data provided by selected device                      */
      switch (adr) {
      switch (adr) {
        case ATA_ASR :
        case ATA_ASR :
          ata_device_debug(4, "alternate_status register read\n");
          ata_device_debug(4, "alternate_status register read\n");
          if ( (device->regs.device_head & ATA_DHR_DEV) ==  device->internals.dev )
          if ( (device->regs.device_head & ATA_DHR_DEV) ==  device->internals.dev )
              return device -> regs.status;
              return device -> regs.status;
          else
          else
          {
          {
              ata_device_debug(2, "device0 responds for device1, asr = 0x00\n");
              ata_device_debug(2, "device0 responds for device1, asr = 0x00\n");
              return 0; // return 0 when device0 responds for device1
              return 0; // return 0 when device0 responds for device1
          }
          }
 
 
        case ATA_CHR :
        case ATA_CHR :
          ata_device_debug(4, "cylinder_high register read, value = 0x%02X\n",
          ata_device_debug(4, "cylinder_high register read, value = 0x%02X\n",
                 device->regs.cylinder_high);
                 device->regs.cylinder_high);
          return device -> regs.cylinder_high;
          return device -> regs.cylinder_high;
 
 
        case ATA_CLR :
        case ATA_CLR :
          ata_device_debug(4, "cylinder_low register read, value = 0x%02X\n",
          ata_device_debug(4, "cylinder_low register read, value = 0x%02X\n",
                 device->regs.cylinder_low);
                 device->regs.cylinder_low);
          return device -> regs.cylinder_low;
          return device -> regs.cylinder_low;
 
 
        case ATA_DR  :
        case ATA_DR  :
          if (!device->regs.status & ATA_SR_DRQ)
          if (!device->regs.status & ATA_SR_DRQ)
          {
          {
             ata_device_debug(1, "data register read, while DRQ bit negated\n" );
             ata_device_debug(1, "data register read, while DRQ bit negated\n" );
             return 0;
             return 0;
          }
          }
          else
          else
          {
          {
              ata_device_debug(4, "data register read, value = 0x%04X, cnt = %3d\n",
              ata_device_debug(4, "data register read, value = 0x%04X, cnt = %3d\n",
                     *device->internals.dbuf_ptr, device->internals.dbuf_cnt);
                     *device->internals.dbuf_ptr, device->internals.dbuf_cnt);
              if (!--device->internals.dbuf_cnt)
              if (!--device->internals.dbuf_cnt)
                   device->regs.status &= ~ATA_SR_DRQ;
                   device->regs.status &= ~ATA_SR_DRQ;
              return *device -> internals.dbuf_ptr++;
              return *device -> internals.dbuf_ptr++;
          }
          }
 
 
        case ATA_DHR :
        case ATA_DHR :
          ata_device_debug(4, "device_head register read, value = 0x%02X\n",
          ata_device_debug(4, "device_head register read, value = 0x%02X\n",
                 device->regs.device_head);
                 device->regs.device_head);
          return device -> regs.device_head;
          return device -> regs.device_head;
 
 
        case ATA_ERR :
        case ATA_ERR :
          ata_device_debug(4, "error register read, value = 0x%02X\n",
          ata_device_debug(4, "error register read, value = 0x%02X\n",
                 device->regs.error);
                 device->regs.error);
          return device -> regs.error;
          return device -> regs.error;
 
 
        case ATA_SCR :
        case ATA_SCR :
          ata_device_debug(4, "sectorcount register read, value = 0x%02X\n",
          ata_device_debug(4, "sectorcount register read, value = 0x%02X\n",
                 device->regs.sector_count);
                 device->regs.sector_count);
          return device -> regs.sector_count;
          return device -> regs.sector_count;
 
 
        case ATA_SNR :
        case ATA_SNR :
          ata_device_debug(4, "sectornumber register read, value = 0x%02X\n",
          ata_device_debug(4, "sectornumber register read, value = 0x%02X\n",
                 device->regs.sector_number);
                 device->regs.sector_number);
          return device -> regs.sector_number;
          return device -> regs.sector_number;
 
 
        case ATA_SR  :
        case ATA_SR  :
          ata_device_debug(4, "status register read\n");
          ata_device_debug(4, "status register read\n");
          if ( (device->regs.device_head & ATA_DHR_DEV) ==  device->internals.dev)
          if ( (device->regs.device_head & ATA_DHR_DEV) ==  device->internals.dev)
              return device -> regs.status;
              return device -> regs.status;
          else
          else
          {
          {
              ata_device_debug(2, "device0 responds for device1, sr = 0x00\n");
              ata_device_debug(2, "device0 responds for device1, sr = 0x00\n");
              return 0; // return 0 when device0 responds for device1
              return 0; // return 0 when device0 responds for device1
          }
          }
 
 
//        case ATA_DA   :
//        case ATA_DA   :
//          return device -> regs.status;
//          return device -> regs.status;
      }
      }
    }
    }
}
}
 
 
 
 
/*
/*
  D E V I C E S _ W R I T E
  D E V I C E S _ W R I T E
*/
*/
/* Write to devices                                                   */
/* Write to devices                                                   */
void ata_devices_write(ata_devices *devices, char adr, short value)
void ata_devices_write(ata_devices *devices, char adr, short value)
{
{
    /* check for no connected devices                                 */
    /* check for no connected devices                                 */
    if (!devices->device0.stream && !devices->device1.stream)
    if (!devices->device0.stream && !devices->device1.stream)
        MSG_ERROR("ata_devices_write, no ata devices connected.");
        MSG_ERROR("ata_devices_write, no ata devices connected.");
    else
    else
    {
    {
      /* first device                                                 */
      /* first device                                                 */
      if (devices->device0.stream)
      if (devices->device0.stream)
          ata_device_write(&devices->device0, adr, value);
          ata_device_write(&devices->device0, adr, value);
 
 
      /* second device                                                */
      /* second device                                                */
      if (devices->device1.stream)
      if (devices->device1.stream)
          ata_device_write(&devices->device1, adr, value);
          ata_device_write(&devices->device1, adr, value);
    }
    }
}
}
 
 
/* write to a single device                                           */
/* write to a single device                                           */
void ata_device_write(ata_device *device, char adr, short value)
void ata_device_write(ata_device *device, char adr, short value)
{
{
    switch (adr) {
    switch (adr) {
        case ATA_CR  :
        case ATA_CR  :
            /*display debug information                               */
            /*display debug information                               */
            ata_device_debug(4, "command register written, value = 0x%02X\n", value);
            ata_device_debug(4, "command register written, value = 0x%02X\n", value);
 
 
            device->regs.command = value;
            device->regs.command = value;
 
 
            /* check command register settings and execute command    */
            /* check command register settings and execute command    */
            ata_device_do_command_register(device);
            ata_device_do_command_register(device);
            break;
            break;
 
 
 
 
        case ATA_CHR :
        case ATA_CHR :
            /*display debug information                               */
            /*display debug information                               */
            ata_device_debug(4, "cylinder high register written, value = 0x%02X\n", value);
            ata_device_debug(4, "cylinder high register written, value = 0x%02X\n", value);
 
 
            device->regs.cylinder_high = value;
            device->regs.cylinder_high = value;
            break;
            break;
 
 
        case ATA_CLR :
        case ATA_CLR :
            /*display debug information                               */
            /*display debug information                               */
            ata_device_debug(4, "cylinder low register written, value = 0x%02X\n", value);
            ata_device_debug(4, "cylinder low register written, value = 0x%02X\n", value);
 
 
            device->regs.cylinder_low = value;
            device->regs.cylinder_low = value;
            break;
            break;
 
 
        case ATA_DR :
        case ATA_DR :
            /*display debug information                               */
            /*display debug information                               */
            ata_device_debug(4, "data register written, value = 0x%04X\n", value);
            ata_device_debug(4, "data register written, value = 0x%04X\n", value);
 
 
            device->regs.dataport_i = value;
            device->regs.dataport_i = value;
            break;
            break;
 
 
        case ATA_DCR :
        case ATA_DCR :
            /*display debug information                               */
            /*display debug information                               */
            ata_device_debug(4, "device control register written, value = 0x%02X\n", value);
            ata_device_debug(4, "device control register written, value = 0x%02X\n", value);
 
 
            device->regs.device_control = value;
            device->regs.device_control = value;
            ata_device_do_control_register(device);
            ata_device_do_control_register(device);
            break;
            break;
 
 
        case ATA_DHR :
        case ATA_DHR :
            /*display debug information                               */
            /*display debug information                               */
            ata_device_debug(4, "device head register written, value = 0x%02X\n", value);
            ata_device_debug(4, "device head register written, value = 0x%02X\n", value);
 
 
            device->regs.device_head = value;
            device->regs.device_head = value;
            break;
            break;
 
 
        case ATA_FR  :
        case ATA_FR  :
            /*display debug information                               */
            /*display debug information                               */
            ata_device_debug(4, "features register written, value = 0x%02X\n", value);
            ata_device_debug(4, "features register written, value = 0x%02X\n", value);
 
 
            device->regs.features = value;
            device->regs.features = value;
            break;
            break;
 
 
        case ATA_SCR :
        case ATA_SCR :
            /*display debug information                               */
            /*display debug information                               */
            ata_device_debug(4, "sectorcount register written, value = 0x%02X\n", value);
            ata_device_debug(4, "sectorcount register written, value = 0x%02X\n", value);
 
 
            device->regs.sector_count = value;
            device->regs.sector_count = value;
            break;
            break;
 
 
        case ATA_SNR :
        case ATA_SNR :
            /*display debug information                               */
            /*display debug information                               */
            ata_device_debug(4, "sectornumber register written, value = 0x%02X\n", value);
            ata_device_debug(4, "sectornumber register written, value = 0x%02X\n", value);
 
 
            device->regs.sector_number = value;
            device->regs.sector_number = value;
            break;
            break;
 
 
    } //endcase
    } //endcase
}
}
 
 
 
 
/* --------------------------                                         */
/* --------------------------                                         */
/* -- print debug messages --                                         */
/* -- print debug messages --                                         */
/* --------------------------                                         */
/* --------------------------                                         */
int ata_device_debug(int lvl, char *format, ...)
int ata_device_debug(int lvl, char *format, ...)
{
{
  va_list ap;
  va_list ap;
 
 
  va_start(ap, format);
  va_start(ap, format);
 
 
  if (ATA_DEVICE_DEBUG_LVL >= lvl)
  if (ATA_DEVICE_DEBUG_LVL >= lvl)
  {
  {
    fprintf(stderr, "ata_device_debug: ");
    fprintf(stderr, "ata_device_debug: ");
    vfprintf(stderr, format, ap);
    vfprintf(stderr, format, ap);
  }
  }
 
 
  va_end(ap);
  va_end(ap);
  return 0;
  return 0;
}
}
 
 

powered by: WebSVN 2.1.0

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