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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [peripheral/] [atadevice.c] - Diff between revs 60 and 82

Only display areas with differences | Details | Blame | View Log

Rev 60 Rev 82
/* atadevice.c -- ATA Device simulation. Simulates a harddisk, using a local
/* atadevice.c -- ATA Device simulation. Simulates a harddisk, using a local
   streams.
   streams.
 
 
   Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
   Copyright (C) 2002 Richard Herveille, rherveille@opencores.org
   Copyright (C) 2008 Embecosm Limited
   Copyright (C) 2008 Embecosm Limited
 
 
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
 
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
 
 
   This program is free software; you can redistribute it and/or modify it
   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
   under the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 3 of the License, or (at your option)
   Software Foundation; either version 3 of the License, or (at your option)
   any later version.
   any later version.
 
 
   This program is distributed in the hope that it will be useful, but WITHOUT
   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.
   more details.
 
 
   You should have received a copy of the GNU General Public License along
   You should have received a copy of the GNU General Public License along
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
/* This program is commented throughout in a fashion suitable for processing
/* This program is commented throughout in a fashion suitable for processing
   with Doxygen. */
   with Doxygen. */
 
 
 
 
/* Autoconf and/or portability configuration */
/* Autoconf and/or portability configuration */
#include "config.h"
#include "config.h"
#include "port.h"
#include "port.h"
 
 
/* System includes */
/* System includes */
#ifdef __APPLE__
#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
#include <libkern/OSByteOrder.h>
#define bswap_16(x) OSSwapInt16(x)
#define bswap_16(x) OSSwapInt16(x)
#define bswap_32(x) OSSwapInt32(x)
#define bswap_32(x) OSSwapInt32(x)
#define bswap_64(x) OSSwapInt64(x)
#define bswap_64(x) OSSwapInt64(x)
#else
#else
#include <byteswap.h>
#include <byteswap.h>
#endif
#endif
 
 
/* Package includes */
/* Package includes */
#include "atadevice.h"
#include "atadevice.h"
#include "atadevice-cmdi.h"
#include "atadevice-cmdi.h"
#include "atacmd.h"
#include "atacmd.h"
#include "abstract.h"
#include "abstract.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
*/
*/
 
 
 
 
/* Use a file to simulate a hard-disk                                 */
/* Use a file to simulate a hard-disk                                 */
static FILE *
static FILE *
open_file (uint32_t * size, const char *filename)
open_file (uint32_t * 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+")))
      {
      {
        fprintf (stderr, "Warning: ata_open_file, cannot open hd-file %s\n",
        fprintf (stderr, "Warning: ata_open_file, cannot open hd-file %s\n",
                 filename);
                 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                                  */
        for (n = 0; n < *size; n++)
        for (n = 0; n < *size; 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",
    fprintf (stderr, "file %s already exists. Using existing file.\n",
             filename);
             filename);
 
 
  /* 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);
 
 
  return fp;
  return fp;
}
}
 
 
 
 
/* Use a the local filesystem as a hard-disk                          */
/* Use a the local filesystem as a hard-disk                          */
static FILE *
static FILE *
open_local (void)
open_local (void)
{
{
  // TODO:
  // TODO:
  fprintf (stderr, "Warning: Device type LOCAL is not yet supported: "
  fprintf (stderr, "Warning: Device type LOCAL is not yet supported: "
           "Defaulting to device type NO_CONNECT.");
           "Defaulting to device type NO_CONNECT.");
  return NULL;
  return NULL;
}
}
 
 
static void
static void
ata_device_init (struct ata_device * device, int dev)
ata_device_init (struct 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->conf.type)
  switch (device->conf.type)
    {
    {
    case TYPE_NO_CONNECT:
    case TYPE_NO_CONNECT:
      device->conf.stream = NULL;
      device->conf.stream = NULL;
      break;
      break;
 
 
    case TYPE_FILE:
    case TYPE_FILE:
      device->conf.stream = open_file (&device->conf.size, device->conf.file);
      device->conf.stream = open_file (&device->conf.size, device->conf.file);
      break;
      break;
 
 
    case TYPE_LOCAL:
    case TYPE_LOCAL:
      device->conf.stream = open_local ();
      device->conf.stream = open_local ();
      break;
      break;
 
 
    default:
    default:
      fprintf (stderr, "Warning: Illegal device-type %d: "
      fprintf (stderr, "Warning: Illegal device-type %d: "
               "Defaulting to type NO_CONNECT.\n", device->conf.type);
               "Defaulting to type NO_CONNECT.\n", device->conf.type);
      device->conf.stream = NULL;
      device->conf.stream = NULL;
      break;
      break;
    }
    }
 
 
  device->conf.size_sect = device->conf.size / BYTES_PER_SECTOR;
  device->conf.size_sect = device->conf.size / BYTES_PER_SECTOR;
}
}
 
 
/*
/*
  D E V I C E S _ I N I T
  D E V I C E S _ I N I T
*/
*/
void
void
ata_devices_init (struct ata_devices * devices)
ata_devices_init (struct ata_devices * devices)
{
{
  ata_device_init (&devices->device[0], 0);
  ata_device_init (&devices->device[0], 0);
 
 
  if (devices->device[0].conf.type)
  if (devices->device[0].conf.type)
    ata_device_init (&devices->device[1], ATA_DHR_DEV);
    ata_device_init (&devices->device[1], ATA_DHR_DEV);
  else
  else
    ata_device_init (&devices->device[1], 0);
    ata_device_init (&devices->device[1], 0);
}
}
 
 
/*
/*
  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
*/
*/
static void
static void
ata_device_hw_reset (struct ata_device * device, int reset_signal,
ata_device_hw_reset (struct 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 = device->conf.sectors;
          device->internals.sectors_per_track = device->conf.sectors;
          device->internals.heads_per_cylinder = device->conf.heads;
          device->internals.heads_per_cylinder = device->conf.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->conf.packet)
          if (!device->conf.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 if (reset_signal)
  else 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;
 
 
      /* set new state                                              */
      /* set new state                                              */
      device->internals.state = ATA_STATE_HW_RST;
      device->internals.state = ATA_STATE_HW_RST;
    }
    }
}
}
 
 
/* power-on and hardware reset                                        */
/* power-on and hardware reset                                        */
void
void
ata_devices_hw_reset (struct ata_devices * devices, int reset_signal)
ata_devices_hw_reset (struct ata_devices * devices, int reset_signal)
{
{
  /* find device 0                                                    */
  /* find device 0                                                    */
  if ((devices->device[0].conf.stream) && (devices->device[1].conf.stream))
  if ((devices->device[0].conf.stream) && (devices->device[1].conf.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->device[1], reset_signal, 1,        /* assert dasp, this is device1          */
      ata_device_hw_reset (&devices->device[1], reset_signal, 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->device[0], reset_signal,
      ata_device_hw_reset (&devices->device[0], reset_signal,
                           0,
                           0,
                           devices->device[1].sigs.pdiago,
                           devices->device[1].sigs.pdiago,
                           devices->device[1].sigs.daspo);
                           devices->device[1].sigs.daspo);
    }
    }
  else if (devices->device[0].conf.stream)
  else if (devices->device[0].conf.stream)
    {
    {
      /* device0 is device0, there's no device1                         */
      /* device0 is device0, there's no device1                         */
      ata_device_hw_reset (&devices->device[0], reset_signal, 0,  /* negate dasp, this is device0          */
      ata_device_hw_reset (&devices->device[0], reset_signal, 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->device[1].conf.stream)
  else if (devices->device[1].conf.stream)
    {
    {
      /* device1 is (logical) device0, there's no (physical) device0    */
      /* device1 is (logical) device0, there's no (physical) device0    */
      ata_device_hw_reset (&devices->device[1], reset_signal, 0, /* negate dasp, this is device0          */
      ata_device_hw_reset (&devices->device[1], reset_signal, 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 */
    }
    }
}
}
 
 
 
 
/*
/*
  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
*/
*/
static void
static void
ata_device_do_control_register (struct ata_device * device)
ata_device_do_control_register (struct 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;
        }
        }
    }
    }
  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->conf.packet)
      if (!device->conf.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> 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
*/
*/
static void
static void
ata_device_do_command_register (struct ata_device * device)
ata_device_do_command_register (struct ata_device * device)
{
{
  /* check BSY & DRQ                                                  */
  /* check BSY & DRQ                                                  */
  if ((device->regs.status & ATA_SR_BSY)
  if ((device->regs.status & ATA_SR_BSY)
      || (device->regs.status & ATA_SR_DRQ))
      || (device->regs.status & ATA_SR_DRQ))
    {
    {
      if (device->regs.command != DEVICE_RESET)
      if (device->regs.command != DEVICE_RESET)
        {
        {
          fprintf (stderr, "Warning: ata_device_write, writing a command "
          fprintf (stderr, "Warning: ata_device_write, writing a command "
                   "while BSY or DRQ asserted.\n");
                   "while BSY or DRQ asserted.\n");
        }
        }
    }
    }
 
 
  /* 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
short
ata_devices_read (struct ata_devices * devices, char adr)
ata_devices_read (struct ata_devices * devices, char adr)
{
{
  struct ata_device *device;
  struct ata_device *device;
 
 
  /* check for no connected devices                                 */
  /* check for no connected devices                                 */
  if ((!devices->device[0].conf.stream) && (!devices->device[1].conf.stream))
  if ((!devices->device[0].conf.stream) && (!devices->device[1].conf.stream))
    {
    {
      fprintf (stderr, "Warning: ata_devices_read, no ata devices "
      fprintf (stderr, "Warning: ata_devices_read, no ata devices "
               "connected.\n");
               "connected.\n");
    }
    }
  else
  else
    {
    {
      /* check if both device0 and device1 are connected              */
      /* check if both device0 and device1 are connected              */
      if ((devices->device[0].conf.stream)
      if ((devices->device[0].conf.stream)
          && (devices->device[1].conf.stream))
          && (devices->device[1].conf.stream))
        {
        {
          /* get the current active device                            */
          /* get the current active device                            */
          if (devices->device[1].regs.device_head & ATA_DHR_DEV)
          if (devices->device[1].regs.device_head & ATA_DHR_DEV)
            device = &devices->device[1];
            device = &devices->device[1];
          else
          else
            device = &devices->device[0];
            device = &devices->device[0];
        }
        }
      else
      else
        {
        {
          /* only one device connected                                */
          /* only one device connected                                */
          if (devices->device[1].conf.stream)
          if (devices->device[1].conf.stream)
            device = &devices->device[1];
            device = &devices->device[1];
          else
          else
            device = &devices->device[0];
            device = &devices->device[0];
        }
        }
 
 
      /* return data provided by selected device                      */
      /* return data provided by selected device                      */
      switch (adr)
      switch (adr)
        {
        {
        case ATA_ASR:
        case ATA_ASR:
          if ((device->regs.device_head & ATA_DHR_DEV) ==
          if ((device->regs.device_head & ATA_DHR_DEV) ==
              device->internals.dev)
              device->internals.dev)
            return device->regs.status;
            return device->regs.status;
          else
          else
            {
            {
              return 0;          // return 0 when device0 responds for device1
              return 0;          // return 0 when device0 responds for device1
            }
            }
 
 
        case ATA_CHR:
        case ATA_CHR:
          return device->regs.cylinder_high;
          return device->regs.cylinder_high;
 
 
        case ATA_CLR:
        case ATA_CLR:
          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))
            {
            {
              return 0;
              return 0;
            }
            }
          else
          else
            {
            {
              uint16_t val = LE16 (*device->internals.dbuf_ptr++);
              uint16_t val = LE16 (*device->internals.dbuf_ptr++);
              if (!--device->internals.dbuf_cnt)
              if (!--device->internals.dbuf_cnt)
                {
                {
                  device->regs.status &= ~ATA_SR_DRQ;
                  device->regs.status &= ~ATA_SR_DRQ;
                  if (device->internals.end_t_func)
                  if (device->internals.end_t_func)
                    device->internals.end_t_func (device);
                    device->internals.end_t_func (device);
                }
                }
              return val;
              return val;
            }
            }
 
 
        case ATA_DHR:
        case ATA_DHR:
          return device->regs.device_head;
          return device->regs.device_head;
 
 
        case ATA_ERR:
        case ATA_ERR:
          return device->regs.error;
          return device->regs.error;
 
 
        case ATA_SCR:
        case ATA_SCR:
          return device->regs.sector_count;
          return device->regs.sector_count;
 
 
        case ATA_SNR:
        case ATA_SNR:
          return device->regs.sector_number;
          return device->regs.sector_number;
 
 
        case ATA_SR:
        case ATA_SR:
          if ((device->regs.device_head & ATA_DHR_DEV) ==
          if ((device->regs.device_head & ATA_DHR_DEV) ==
              device->internals.dev)
              device->internals.dev)
            {
            {
              device->sigs.intrq = 0;
              device->sigs.intrq = 0;
              return device->regs.status;
              return device->regs.status;
            }
            }
 
 
          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;
        }
        }
    }
    }
  return 0;
  return 0;
}
}
 
 
 
 
/*
/*
  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 a single device                                           */
/* write to a single device                                           */
static void
static void
ata_device_write (struct ata_device * device, char adr, short value)
ata_device_write (struct ata_device * device, char adr, short value)
{
{
  switch (adr)
  switch (adr)
    {
    {
    case ATA_CR:
    case ATA_CR:
      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:
      device->regs.cylinder_high = value;
      device->regs.cylinder_high = value;
      break;
      break;
 
 
    case ATA_CLR:
    case ATA_CLR:
      device->regs.cylinder_low = value;
      device->regs.cylinder_low = value;
      break;
      break;
 
 
    case ATA_DR:
    case ATA_DR:
      if (!device->regs.status & ATA_SR_DRQ)
      if (!(device->regs.status & ATA_SR_DRQ))
        {
        {
          break;
          break;
        }
        }
      else
      else
        {
        {
          *device->internals.dbuf_ptr++ = LE16 (value);
          *device->internals.dbuf_ptr++ = LE16 (value);
          if (!--device->internals.dbuf_cnt)
          if (!--device->internals.dbuf_cnt)
            {
            {
              device->regs.status &= ~ATA_SR_DRQ;
              device->regs.status &= ~ATA_SR_DRQ;
              if (device->internals.end_t_func)
              if (device->internals.end_t_func)
                device->internals.end_t_func (device);
                device->internals.end_t_func (device);
            }
            }
        }
        }
      device->regs.dataport_i = value;
      device->regs.dataport_i = value;
      break;
      break;
 
 
    case ATA_DCR:
    case ATA_DCR:
      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:
      device->regs.device_head = value;
      device->regs.device_head = value;
      break;
      break;
 
 
    case ATA_FR:
    case ATA_FR:
      device->regs.features = value;
      device->regs.features = value;
      break;
      break;
 
 
    case ATA_SCR:
    case ATA_SCR:
      device->regs.sector_count = value;
      device->regs.sector_count = value;
      break;
      break;
 
 
    case ATA_SNR:
    case ATA_SNR:
      device->regs.sector_number = value;
      device->regs.sector_number = value;
      break;
      break;
 
 
    }                           //endcase
    }                           //endcase
}
}
 
 
/* Write to devices                                                   */
/* Write to devices                                                   */
void
void
ata_devices_write (struct ata_devices * devices, char adr, short value)
ata_devices_write (struct ata_devices * devices, char adr, short value)
{
{
  /* check for no connected devices                                 */
  /* check for no connected devices                                 */
  if (!devices->device[0].conf.stream && !devices->device[1].conf.stream)
  if (!devices->device[0].conf.stream && !devices->device[1].conf.stream)
    {
    {
      fprintf (stderr, "Warning: ata_devices_write, no ata devices "
      fprintf (stderr, "Warning: ata_devices_write, no ata devices "
               "connected.\n");
               "connected.\n");
    }
    }
  else
  else
    {
    {
      /* first device                                                 */
      /* first device                                                 */
      if (devices->device[0].conf.stream)
      if (devices->device[0].conf.stream)
        ata_device_write (&devices->device[0], adr, value);
        ata_device_write (&devices->device[0], adr, value);
 
 
      /* second device                                                */
      /* second device                                                */
      if (devices->device[1].conf.stream)
      if (devices->device[1].conf.stream)
        ata_device_write (&devices->device[1], adr, value);
        ata_device_write (&devices->device[1], adr, value);
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

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