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

Subversion Repositories openrisc

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

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

Rev 19 Rev 82
/* atadevice_cmdi.c -- ATA Device simulation
/* atadevice_cmdi.c -- ATA Device simulation
   Command interpreter for the simulated harddisk.
   Command interpreter for the simulated harddisk.
 
 
   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. */
 
 
/* For fun, count the number of FIXMEs :-( */
/* For fun, count the number of FIXMEs :-( */
 
 
 
 
/* Autoconf and/or portability configuration */
/* Autoconf and/or portability configuration */
#include "config.h"
#include "config.h"
 
 
/* Package includes */
/* Package includes */
#include "atadevice-cmdi.h"
#include "atadevice-cmdi.h"
#include "atahost.h"
#include "atahost.h"
#include "atacmd.h"
#include "atacmd.h"
#include "sched.h"
#include "sched.h"
 
 
 
 
/* FIXME: If device0 is not selected and then an interrupt occurs and
/* FIXME: If device0 is not selected and then an interrupt occurs and
 * then it is selected, the interrupt should be delivered, but I just drop it
 * then it is selected, the interrupt should be delivered, but I just drop it
 * (same goes for device 1). */
 * (same goes for device 1). */
static void
static void
ata_cmd_complete (void *dat)
ata_cmd_complete (void *dat)
{
{
  struct ata_device *dev = dat;
  struct ata_device *dev = dat;
 
 
  dev->regs.status &= ~ATA_SR_BSY;
  dev->regs.status &= ~ATA_SR_BSY;
 
 
  if (dev->regs.device_control & ATA_DCR_IEN)
  if (dev->regs.device_control & ATA_DCR_IEN)
    return;
    return;
 
 
  if ((dev->regs.device_head & ATA_DHR_DEV) != dev->internals.dev)
  if ((dev->regs.device_head & ATA_DHR_DEV) != dev->internals.dev)
    return;
    return;
 
 
  if (dev->sigs.intrq)
  if (dev->sigs.intrq)
    return;
    return;
 
 
  dev->sigs.intrq = 1;
  dev->sigs.intrq = 1;
  ata_int (dev->internals.host);
  ata_int (dev->internals.host);
}
}
 
 
static void
static void
ata_set_sect (struct ata_device *dev, uint32_t sect)
ata_set_sect (struct ata_device *dev, uint32_t sect)
{
{
  uint16_t cyl;
  uint16_t cyl;
 
 
  dev->regs.device_head &= ~ATA_DHR_H;
  dev->regs.device_head &= ~ATA_DHR_H;
  if (dev->regs.device_head & ATA_DHR_LBA)
  if (dev->regs.device_head & ATA_DHR_LBA)
    {
    {
      dev->regs.sector_number = sect & 0xff;
      dev->regs.sector_number = sect & 0xff;
      dev->regs.cylinder_low = (sect >> 8) & 0xff;
      dev->regs.cylinder_low = (sect >> 8) & 0xff;
      dev->regs.cylinder_high = (sect >> 16) & 0xff;
      dev->regs.cylinder_high = (sect >> 16) & 0xff;
      dev->regs.device_head |= (sect >> 24) & 0xf;
      dev->regs.device_head |= (sect >> 24) & 0xf;
    }
    }
  else
  else
    {
    {
      cyl = sect / (dev->conf.heads * dev->conf.sectors);
      cyl = sect / (dev->conf.heads * dev->conf.sectors);
      dev->regs.cylinder_low = cyl & 0xff;
      dev->regs.cylinder_low = cyl & 0xff;
      dev->regs.cylinder_high = (cyl >> 8) & 0xff;
      dev->regs.cylinder_high = (cyl >> 8) & 0xff;
 
 
      cyl = sect % (dev->conf.heads * dev->conf.sectors);
      cyl = sect % (dev->conf.heads * dev->conf.sectors);
      dev->regs.sector_number = (cyl % dev->conf.sectors) + 1;
      dev->regs.sector_number = (cyl % dev->conf.sectors) + 1;
      dev->regs.device_head |= (cyl / dev->conf.sectors) & 0xf;
      dev->regs.device_head |= (cyl / dev->conf.sectors) & 0xf;
    }
    }
}
}
 
 
/* Returns the concatenated lba address from the values in the addr regs */
/* Returns the concatenated lba address from the values in the addr regs */
static uint32_t
static uint32_t
ata_calc_lba (struct ata_device *dev)
ata_calc_lba (struct ata_device *dev)
{
{
  uint32_t lba;
  uint32_t lba;
 
 
  /* check if we are using CHS or LBA translation, fill in the bits */
  /* check if we are using CHS or LBA translation, fill in the bits */
  if (dev->regs.device_head & ATA_DHR_LBA)
  if (dev->regs.device_head & ATA_DHR_LBA)
    {
    {
      /* we are using LBA translation                               */
      /* we are using LBA translation                               */
      lba = (dev->regs.device_head & ATA_DHR_H) << 24 |
      lba = (dev->regs.device_head & ATA_DHR_H) << 24 |
        (dev->regs.cylinder_high) << 16 |
        (dev->regs.cylinder_high) << 16 |
        (dev->regs.cylinder_low) << 8 | dev->regs.sector_number;
        (dev->regs.cylinder_low) << 8 | dev->regs.sector_number;
    }
    }
  else
  else
    {
    {
      /* we are using CHS translation, calculate lba address        */
      /* we are using CHS translation, calculate lba address        */
      lba = (dev->regs.cylinder_high << 16) | dev->regs.cylinder_low;
      lba = (dev->regs.cylinder_high << 16) | dev->regs.cylinder_low;
      lba *= dev->internals.heads_per_cylinder;
      lba *= dev->internals.heads_per_cylinder;
      lba += dev->regs.device_head & ATA_DHR_H;
      lba += dev->regs.device_head & ATA_DHR_H;
      lba *= dev->internals.sectors_per_track;
      lba *= dev->internals.sectors_per_track;
      lba += dev->regs.sector_number;
      lba += dev->regs.sector_number;
      lba -= 1;
      lba -= 1;
    }
    }
  return lba;
  return lba;
}
}
 
 
/* Reads a sector from the device */
/* Reads a sector from the device */
static void
static void
ata_read_sect (struct ata_device *dev)
ata_read_sect (struct ata_device *dev)
{
{
  if (!dev->internals.nr_sect)
  if (!dev->internals.nr_sect)
    return;
    return;
 
 
  /* set the file-positon pointer to the start of the sector    */
  /* set the file-positon pointer to the start of the sector    */
  fseek (dev->conf.stream, dev->internals.lba, SEEK_SET);
  fseek (dev->conf.stream, dev->internals.lba, SEEK_SET);
 
 
  /* get the bytes from the stream                              */
  /* get the bytes from the stream                              */
  fread (dev->internals.dbuf, BYTES_PER_SECTOR, 1, dev->conf.stream);
  if (1 != fread (dev->internals.dbuf, BYTES_PER_SECTOR, 1, dev->conf.stream))
 
    {
 
      printf ("WARNING atadevice read short\n");
 
    }
 
 
  /* set status register bits                                   */
  /* set status register bits                                   */
  dev->regs.status = ATA_SR_DRDY | ATA_SR_DRQ;
  dev->regs.status = ATA_SR_DRDY | ATA_SR_DRQ;
 
 
  /* reset the databuffer                                       */
  /* reset the databuffer                                       */
  dev->internals.dbuf_cnt = BYTES_PER_SECTOR / 2;       //Words, not bytes
  dev->internals.dbuf_cnt = BYTES_PER_SECTOR / 2;       //Words, not bytes
  dev->internals.dbuf_ptr = dev->internals.dbuf;
  dev->internals.dbuf_ptr = dev->internals.dbuf;
 
 
  dev->internals.lba += BYTES_PER_SECTOR;
  dev->internals.lba += BYTES_PER_SECTOR;
  dev->internals.nr_sect--;
  dev->internals.nr_sect--;
 
 
  SCHED_ADD (ata_cmd_complete, dev, 400000);
  SCHED_ADD (ata_cmd_complete, dev, 400000);
}
}
 
 
/* Writes a sector to the device */
/* Writes a sector to the device */
static void
static void
ata_write_sect (struct ata_device *dev)
ata_write_sect (struct ata_device *dev)
{
{
  if (!dev->internals.nr_sect)
  if (!dev->internals.nr_sect)
    {
    {
      dev->regs.status = ATA_SR_DRDY;
      dev->regs.status = ATA_SR_DRDY;
      return;
      return;
    }
    }
 
 
  /* set the file-positon pointer to the start of the sector    */
  /* set the file-positon pointer to the start of the sector    */
  fseek (dev->conf.stream, dev->internals.lba, SEEK_SET);
  fseek (dev->conf.stream, dev->internals.lba, SEEK_SET);
 
 
  /* get the bytes from the stream                              */
  /* get the bytes from the stream                              */
  fwrite (dev->internals.dbuf, BYTES_PER_SECTOR, 1, dev->conf.stream);
  fwrite (dev->internals.dbuf, BYTES_PER_SECTOR, 1, dev->conf.stream);
 
 
  /* set status register bits                                   */
  /* set status register bits                                   */
  dev->regs.status = ATA_SR_DRDY | ATA_SR_DRQ | ATA_SR_DSC | ATA_SR_BSY;
  dev->regs.status = ATA_SR_DRDY | ATA_SR_DRQ | ATA_SR_DSC | ATA_SR_BSY;
 
 
  /* reset the databuffer                                       */
  /* reset the databuffer                                       */
  dev->internals.dbuf_cnt = BYTES_PER_SECTOR / 2;       //Words, not bytes
  dev->internals.dbuf_cnt = BYTES_PER_SECTOR / 2;       //Words, not bytes
  dev->internals.dbuf_ptr = dev->internals.dbuf;
  dev->internals.dbuf_ptr = dev->internals.dbuf;
 
 
  dev->internals.lba += BYTES_PER_SECTOR;
  dev->internals.lba += BYTES_PER_SECTOR;
  if (!--dev->internals.nr_sect)
  if (!--dev->internals.nr_sect)
    dev->regs.status = ATA_SR_DRDY | ATA_SR_DSC | ATA_SR_BSY;
    dev->regs.status = ATA_SR_DRDY | ATA_SR_DSC | ATA_SR_BSY;
 
 
  SCHED_ADD (ata_cmd_complete, dev, 40000);
  SCHED_ADD (ata_cmd_complete, dev, 40000);
}
}
 
 
 
 
/*
/*
  A T A _ S E T _ D E V I C E _ S I G N A T U R E
  A T A _ S E T _ D E V I C E _ S I G N A T U R E
 
 
  called whenever a command needs to signal the device type (packet, non-packet)
  called whenever a command needs to signal the device type (packet, non-packet)
*/
*/
static void
static void
ata_set_device_signature (struct ata_device *device, int packet)
ata_set_device_signature (struct ata_device *device, int packet)
{
{
  if (packet)
  if (packet)
    {
    {
      /* place PACKET Command feature set signature in register block   */
      /* place PACKET Command feature set signature in register block   */
      device->regs.sector_count = 0x01;
      device->regs.sector_count = 0x01;
      device->regs.sector_number = 0x01;
      device->regs.sector_number = 0x01;
      device->regs.cylinder_low = 0x14;
      device->regs.cylinder_low = 0x14;
      device->regs.cylinder_high = 0xEB;
      device->regs.cylinder_high = 0xEB;
    }
    }
  else
  else
    {
    {
      /* place NON_PACKET Command feature set signature in register block */
      /* place NON_PACKET Command feature set signature in register block */
      device->regs.sector_count = 0x01;
      device->regs.sector_count = 0x01;
      device->regs.sector_number = 0x01;
      device->regs.sector_number = 0x01;
      device->regs.cylinder_low = 0x00;
      device->regs.cylinder_low = 0x00;
      device->regs.cylinder_high = 0x00;
      device->regs.cylinder_high = 0x00;
      device->regs.device_head = 0x00;
      device->regs.device_head = 0x00;
    }
    }
}
}
 
 
 
 
/*
/*
  A T A _ E X E C U T E _ D E V I C E _ D I A G N O S T I C S
  A T A _ E X E C U T E _ D E V I C E _ D I A G N O S T I C S
*/
*/
void
void
ata_execute_device_diagnostics_cmd (struct ata_device *device)
ata_execute_device_diagnostics_cmd (struct ata_device *device)
{
{
  /* clear SRST bit, if set                                           */
  /* clear SRST bit, if set                                           */
  device->regs.device_control &= ~ATA_DCR_RST;
  device->regs.device_control &= ~ATA_DCR_RST;
 
 
  /* content of features register is undefined                        */
  /* content of features register is undefined                        */
 
 
  /*
  /*
     set device error register
     set device error register
     Device0: 0x01 = Device0 passed & Device1 passed/not present
     Device0: 0x01 = Device0 passed & Device1 passed/not present
     Device1: 0x01 = Device1 passed
     Device1: 0x01 = Device1 passed
   */
   */
  device->regs.error = 0x01;
  device->regs.error = 0x01;
  /* something about DASP- and error_register_bit7                    */
  /* something about DASP- and error_register_bit7                    */
  /* if device1 is not present or if device1 is present and passed    */
  /* if device1 is not present or if device1 is present and passed    */
  /* diagnostics, than bit7 should be cleared.                        */
  /* diagnostics, than bit7 should be cleared.                        */
  /* This means we always clear bit7                                  */
  /* This means we always clear bit7                                  */
 
 
 
 
  /* check if device implements packet protocol                       */
  /* check if device implements packet protocol                       */
  if (device->conf.packet)
  if (device->conf.packet)
    {
    {
      /* place PACKET command feature set signature in register block   */
      /* place PACKET command feature set signature in register block   */
      ata_set_device_signature (device, 1);
      ata_set_device_signature (device, 1);
 
 
      device->regs.status &= 0xf8;
      device->regs.status &= 0xf8;
 
 
      if (device->regs.command == DEVICE_RESET)
      if (device->regs.command == DEVICE_RESET)
        device->regs.device_head = device->regs.device_head & ATA_DHR_LBA;
        device->regs.device_head = device->regs.device_head & ATA_DHR_LBA;
      else
      else
        device->regs.device_head = 0x00;
        device->regs.device_head = 0x00;
    }
    }
  else
  else
    {
    {
      /* place NON_PACKET Command feature set signature in register block */
      /* place NON_PACKET Command feature set signature in register block */
      ata_set_device_signature (device, 0);
      ata_set_device_signature (device, 0);
 
 
      device->regs.status &= 0x82;
      device->regs.status &= 0x82;
    }
    }
 
 
 
 
  /* we passed diagnostics, so set the PDIAG-line                     */
  /* we passed diagnostics, so set the PDIAG-line                     */
  device->sigs.pdiago = 1;
  device->sigs.pdiago = 1;
}
}
 
 
 
 
/*
/*
  A T A _ D E V I C E _ R E S E T
  A T A _ D E V I C E _ R E S E T
*/
*/
static void
static void
ata_device_reset_cmd (struct ata_device *device)
ata_device_reset_cmd (struct ata_device *device)
{
{
  if (!device->conf.packet)
  if (!device->conf.packet)
    {
    {
      fprintf( stderr, "Warning: executing DEVICE_RESET on non-packet "
      fprintf( stderr, "Warning: executing DEVICE_RESET on non-packet "
               "device\n");
               "device\n");
    }
    }
 
 
  ata_execute_device_diagnostics_cmd (device);
  ata_execute_device_diagnostics_cmd (device);
}
}
 
 
 
 
/*
/*
  A T A _ I D E N T I F Y _ D E V I C E
  A T A _ I D E N T I F Y _ D E V I C E
*/
*/
static void
static void
ata_identify_device_cmd (struct ata_device *device)
ata_identify_device_cmd (struct ata_device *device)
{
{
  unsigned char *chksum_buf, chksum;
  unsigned char *chksum_buf, chksum;
  unsigned short *buf;
  unsigned short *buf;
  int n;
  int n;
  unsigned int tmp;
  unsigned int tmp;
 
 
  /* reset databuffer                                                 */
  /* reset databuffer                                                 */
  device->internals.dbuf_cnt = 256;
  device->internals.dbuf_cnt = 256;
  device->internals.dbuf_ptr = device->internals.dbuf;
  device->internals.dbuf_ptr = device->internals.dbuf;
  device->internals.end_t_func = NULL;
  device->internals.end_t_func = NULL;
 
 
  buf = device->internals.dbuf;
  buf = device->internals.dbuf;
  chksum_buf = (unsigned char *) buf;
  chksum_buf = (unsigned char *) buf;
 
 
  /*
  /*
     if number_of_available_sectors (==device->size / BYTES_PER_SECTOR) < 16,514,064 then
     if number_of_available_sectors (==device->size / BYTES_PER_SECTOR) < 16,514,064 then
     support CHS translation where:
     support CHS translation where:
     LBA = ( ((cylinder_number*heads_per_cylinder) +head_number) *sectors_per_track ) +sector_number -1;
     LBA = ( ((cylinder_number*heads_per_cylinder) +head_number) *sectors_per_track ) +sector_number -1;
 
 
     Cylinders : 1-255   (or max.cylinders)
     Cylinders : 1-255   (or max.cylinders)
     Heads     : 0-15    (or max.heads    )
     Heads     : 0-15    (or max.heads    )
     Sectors   : 0-65535 (or max.sectors  )
     Sectors   : 0-65535 (or max.sectors  )
   */
   */
 
 
  /*
  /*
     1) Word 1 shall contain the number of user-addressable logical cylinders in the default CHS
     1) Word 1 shall contain the number of user-addressable logical cylinders in the default CHS
     translation. If the content of words (61:60) is less than 16,514,064 then the content of word 1
     translation. If the content of words (61:60) is less than 16,514,064 then the content of word 1
     shall be greater than or equal to one and less than or equal to 65,535. If the content of words
     shall be greater than or equal to one and less than or equal to 65,535. If the content of words
     (61:60) is greater than or equal to 16,514,064 then the content of
     (61:60) is greater than or equal to 16,514,064 then the content of
     word 1 shall be equal to 16,383.
     word 1 shall be equal to 16,383.
     2) Word 3 shall contain the number of user-addressable logical heads in the default CHS
     2) Word 3 shall contain the number of user-addressable logical heads in the default CHS
     translation. The content of word 3 shall be greater than or equal to one and less than or equal to
     translation. The content of word 3 shall be greater than or equal to one and less than or equal to
     16. For compatibility with some BIOSs, the content of word 3 may be equal to 15 if the content of
     16. For compatibility with some BIOSs, the content of word 3 may be equal to 15 if the content of
     word 1 is greater than 8192.
     word 1 is greater than 8192.
     3) Word 6 shall contain the number of user-addressable logical sectors in the default CHS
     3) Word 6 shall contain the number of user-addressable logical sectors in the default CHS
     translation. The content of word 6 shall be greater than or equal to one and less than or equal to
     translation. The content of word 6 shall be greater than or equal to one and less than or equal to
     63.
     63.
     4) [(The content of word 1) * (the content of word 3) * (the content of word 6)] shall be less than or
     4) [(The content of word 1) * (the content of word 3) * (the content of word 6)] shall be less than or
     equal to 16,514,064
     equal to 16,514,064
     5) Word 54 shall contain the number of user-addressable logical cylinders in the current CHS
     5) Word 54 shall contain the number of user-addressable logical cylinders in the current CHS
     translation. The content of word 54 shall be greater than or equal to one and less than or
     translation. The content of word 54 shall be greater than or equal to one and less than or
     equal to 65,535. After power-on of after a hardware reset the content of word 54 shall be equal to
     equal to 65,535. After power-on of after a hardware reset the content of word 54 shall be equal to
     the content of word 1.
     the content of word 1.
     6) Word 55 shall contain the number of user-addressable logical heads in the current CHS
     6) Word 55 shall contain the number of user-addressable logical heads in the current CHS
     translation. The content of word 55 shall be greater than or equal to one and less than or equal
     translation. The content of word 55 shall be greater than or equal to one and less than or equal
     to 16. After power-on or after a hardware reset the content of word 55 shall equal the content of
     to 16. After power-on or after a hardware reset the content of word 55 shall equal the content of
     word 3.
     word 3.
     7) Word 56 shall contain the user-addressable logical sectors in the current CHS
     7) Word 56 shall contain the user-addressable logical sectors in the current CHS
     translation. The content of word 56 should be equal to 63 for compatibility with all BIOSs.
     translation. The content of word 56 should be equal to 63 for compatibility with all BIOSs.
     However, the content of word 56 may be greater than or equal to one and less than or equal to
     However, the content of word 56 may be greater than or equal to one and less than or equal to
     255. At power-on or after a hardware reset the content of word 56 shall equal the content of
     255. At power-on or after a hardware reset the content of word 56 shall equal the content of
     word 6.
     word 6.
     8) Words (58:57) shall contain the user-addressable capacity in sectors for the current CHS
     8) Words (58:57) shall contain the user-addressable capacity in sectors for the current CHS
     translation. The content of words (58:57) shall equal [(the content of word 54) * (the content of
     translation. The content of words (58:57) shall equal [(the content of word 54) * (the content of
     word 55) * (the content of word 56)] The content of words (58:57) shall be less than or equal to
     word 55) * (the content of word 56)] The content of words (58:57) shall be less than or equal to
     16,514,064. The content of words (58:57) shall be less than or equal to the content of words
     16,514,064. The content of words (58:57) shall be less than or equal to the content of words
     (61:60).
     (61:60).
     9) The content of words 54, 55, 56, and (58:57) may be affected by the host issuing an INITIALIZE
     9) The content of words 54, 55, 56, and (58:57) may be affected by the host issuing an INITIALIZE
     DEVICE PARAMETERS command.
     DEVICE PARAMETERS command.
     10)If the content of words (61:60) is greater than 16,514,064 and if the device does not support CHS
     10)If the content of words (61:60) is greater than 16,514,064 and if the device does not support CHS
     addressing, then the content of words 1, 3, 6, 54, 55, 56, and (58:57) shall equal zero. If the
     addressing, then the content of words 1, 3, 6, 54, 55, 56, and (58:57) shall equal zero. If the
     content of word 1, word 3, or word 6 equals zero, then the content of words 1, 3, 6, 54, 55, 56,
     content of word 1, word 3, or word 6 equals zero, then the content of words 1, 3, 6, 54, 55, 56,
     and (58:57) shall equal zero.
     and (58:57) shall equal zero.
     11)Words (61:60) shall contain the total number of user-addressable sectors. The content of words
     11)Words (61:60) shall contain the total number of user-addressable sectors. The content of words
     (61:60) shall be greater than or equal to one and less than or equal to 268,435,456.
     (61:60) shall be greater than or equal to one and less than or equal to 268,435,456.
     12)The content of words 1, 54, (58:57), and (61:60) may be affected by the host issuing a SET MAX
     12)The content of words 1, 54, (58:57), and (61:60) may be affected by the host issuing a SET MAX
     ADDRESS command.
     ADDRESS command.
   */
   */
 
 
 
 
  /* check if this is a NON-PACKET device                             */
  /* check if this is a NON-PACKET device                             */
  if (device->conf.packet)
  if (device->conf.packet)
    {
    {
      /*
      /*
         This is a PACKET device.
         This is a PACKET device.
         Respond by placing PACKET Command feature set signature in block registers.
         Respond by placing PACKET Command feature set signature in block registers.
         Abort command.
         Abort command.
       */
       */
 
 
      ata_set_device_signature (device, 1);
      ata_set_device_signature (device, 1);
      device->regs.status = ATA_SR_ERR;
      device->regs.status = ATA_SR_ERR;
      device->regs.error = ATA_ERR_ABT;
      device->regs.error = ATA_ERR_ABT;
    }
    }
  else
  else
    {
    {
      /* start filling buffer                                           */
      /* start filling buffer                                           */
 
 
      /*
      /*
         word 0: General configuration
         word 0: General configuration
         15  : 0 = ATA device
         15  : 0 = ATA device
         14-8: retired
         14-8: retired
         7   : 1 = removable media device (not set)
         7   : 1 = removable media device (not set)
         6   : 1 = not-removable controller and/or device (set)
         6   : 1 = not-removable controller and/or device (set)
         5-0 : retired and/or always set to zero
         5-0 : retired and/or always set to zero
       */
       */
      *buf++ = 0x0040;
      *buf++ = 0x0040;
 
 
      /*
      /*
         word 1: Number of logical cylinders
         word 1: Number of logical cylinders
 
 
         >=1, <= 65535
         >=1, <= 65535
       */
       */
      if ((tmp = device->conf.size_sect) >= 16514064)
      if ((tmp = device->conf.size_sect) >= 16514064)
        *buf++ = 16383;
        *buf++ = 16383;
      else
      else
        if ((tmp /= (device->conf.heads + 1) * device->conf.sectors) > 65535)
        if ((tmp /= (device->conf.heads + 1) * device->conf.sectors) > 65535)
        *buf++ = 65535;
        *buf++ = 65535;
      else
      else
        *buf++ = tmp;
        *buf++ = tmp;
 
 
      /*
      /*
         word 2: Specific configuration
         word 2: Specific configuration
 
 
         0x37c8: Device requires SET_FEATURES subcommand to spinup after power-on
         0x37c8: Device requires SET_FEATURES subcommand to spinup after power-on
         and IDENTIFY_DEVICE response is incomplete
         and IDENTIFY_DEVICE response is incomplete
         0x738c: Device requires SET_FEATURES subcommand to spinup after power-on
         0x738c: Device requires SET_FEATURES subcommand to spinup after power-on
         and IDENTIFY_DEVICE response is complete
         and IDENTIFY_DEVICE response is complete
         0x8c73: Device does not require SET_FEATURES subcommand to spinup after power-on
         0x8c73: Device does not require SET_FEATURES subcommand to spinup after power-on
         and IDENTIFY_DEVICE response is incomplete
         and IDENTIFY_DEVICE response is incomplete
         0xc837: Device does not require SET_FEATURES subcommand to spinup after power-on
         0xc837: Device does not require SET_FEATURES subcommand to spinup after power-on
         and IDENTIFY_DEVICE response is complete
         and IDENTIFY_DEVICE response is complete
 
 
         pick-one
         pick-one
       */
       */
      *buf++ = 0xc837;
      *buf++ = 0xc837;
 
 
      /*
      /*
         word 3: Number of logical heads
         word 3: Number of logical heads
 
 
         >= 1, <= 16
         >= 1, <= 16
 
 
         set to 15 if word1 > 8192 (BIOS compatibility)
         set to 15 if word1 > 8192 (BIOS compatibility)
       */
       */
      *buf++ = device->conf.heads;
      *buf++ = device->conf.heads;
 
 
      /*
      /*
         word 5-4: retired
         word 5-4: retired
       */
       */
      buf += 2;
      buf += 2;
 
 
      /*
      /*
         word 6: Number of logical sectors per logical track
         word 6: Number of logical sectors per logical track
 
 
         >= 1, <= 63
         >= 1, <= 63
       */
       */
      *buf++ = device->conf.sectors;
      *buf++ = device->conf.sectors;
 
 
      /*
      /*
         word 8-7: Reserved by the CompactFLASH association
         word 8-7: Reserved by the CompactFLASH association
       */
       */
      buf += 2;
      buf += 2;
 
 
      /*
      /*
         word 9: retired
         word 9: retired
       */
       */
      buf++;
      buf++;
 
 
      /*
      /*
         word 19-10: Serial number (ASCII)
         word 19-10: Serial number (ASCII)
       */
       */
      /*           " www.opencores.org  "                               */
      /*           " www.opencores.org  "                               */
      *buf++ = (' ' << 8) | 'w';
      *buf++ = (' ' << 8) | 'w';
      *buf++ = ('w' << 8) | 'w';
      *buf++ = ('w' << 8) | 'w';
      *buf++ = ('.' << 8) | 'o';
      *buf++ = ('.' << 8) | 'o';
      *buf++ = ('p' << 8) | 'e';
      *buf++ = ('p' << 8) | 'e';
      *buf++ = ('n' << 8) | 'c';
      *buf++ = ('n' << 8) | 'c';
      *buf++ = ('o' << 8) | 'r';
      *buf++ = ('o' << 8) | 'r';
      *buf++ = ('e' << 8) | 's';
      *buf++ = ('e' << 8) | 's';
      *buf++ = ('.' << 8) | 'o';
      *buf++ = ('.' << 8) | 'o';
      *buf++ = ('r' << 8) | 'g';
      *buf++ = ('r' << 8) | 'g';
      *buf++ = (' ' << 8) | ' ';
      *buf++ = (' ' << 8) | ' ';
 
 
      /*
      /*
         word 22   : obsolete
         word 22   : obsolete
         word 21-20: retired
         word 21-20: retired
       */
       */
      buf += 3;
      buf += 3;
 
 
      /*
      /*
         word 26-23: Firmware revision
         word 26-23: Firmware revision
       */
       */
      strncpy ((char *) buf, device->conf.firmware, 8);
      strncpy ((char *) buf, device->conf.firmware, 8);
      buf += 4;
      buf += 4;
 
 
      /*
      /*
         word 46-27: Model number
         word 46-27: Model number
       */
       */
      /*           " ata device model  (C)Richard Herveille "           */
      /*           " ata device model  (C)Richard Herveille "           */
      *buf++ = (' ' << 8) | 'a';
      *buf++ = (' ' << 8) | 'a';
      *buf++ = ('t' << 8) | 'a';
      *buf++ = ('t' << 8) | 'a';
      *buf++ = (' ' << 8) | 'd';
      *buf++ = (' ' << 8) | 'd';
      *buf++ = ('e' << 8) | 'v';
      *buf++ = ('e' << 8) | 'v';
      *buf++ = ('i' << 8) | 'c';
      *buf++ = ('i' << 8) | 'c';
      *buf++ = ('e' << 8) | ' ';
      *buf++ = ('e' << 8) | ' ';
      *buf++ = ('m' << 8) | 'o';
      *buf++ = ('m' << 8) | 'o';
      *buf++ = ('d' << 8) | 'e';
      *buf++ = ('d' << 8) | 'e';
      *buf++ = ('l' << 8) | ' ';
      *buf++ = ('l' << 8) | ' ';
      *buf++ = (' ' << 8) | '(';
      *buf++ = (' ' << 8) | '(';
      *buf++ = ('C' << 8) | ')';
      *buf++ = ('C' << 8) | ')';
      *buf++ = ('R' << 8) | 'i';
      *buf++ = ('R' << 8) | 'i';
      *buf++ = ('c' << 8) | 'h';
      *buf++ = ('c' << 8) | 'h';
      *buf++ = ('a' << 8) | 'r';
      *buf++ = ('a' << 8) | 'r';
      *buf++ = ('d' << 8) | ' ';
      *buf++ = ('d' << 8) | ' ';
      *buf++ = ('H' << 8) | 'e';
      *buf++ = ('H' << 8) | 'e';
      *buf++ = ('r' << 8) | 'v';
      *buf++ = ('r' << 8) | 'v';
      *buf++ = ('e' << 8) | 'i';
      *buf++ = ('e' << 8) | 'i';
      *buf++ = ('l' << 8) | 'l';
      *buf++ = ('l' << 8) | 'l';
      *buf++ = ('e' << 8) | ' ';
      *buf++ = ('e' << 8) | ' ';
 
 
      /*
      /*
         word 47:
         word 47:
         15-8: 0x80
         15-8: 0x80
         7-0: 0x00 reserved
         7-0: 0x00 reserved
         0x01-0xff maximum number of sectors to be transfered
         0x01-0xff maximum number of sectors to be transfered
         per interrupt on a READ/WRITE MULTIPLE command
         per interrupt on a READ/WRITE MULTIPLE command
       */
       */
      *buf++ = 0x8001;
      *buf++ = 0x8001;
 
 
      /*
      /*
         word 48: reserved
         word 48: reserved
       */
       */
      buf++;
      buf++;
 
 
      /*
      /*
         word 49: Capabilities
         word 49: Capabilities
         15-14: reserved for IDENTIFY PACKET DEVICE
         15-14: reserved for IDENTIFY PACKET DEVICE
         13   : 1=standby timers are supported
         13   : 1=standby timers are supported
         0=standby timers are handled by the device FIXME
         0=standby timers are handled by the device FIXME
         12   : reserved for IDENTIFY PACKET DEVICE
         12   : reserved for IDENTIFY PACKET DEVICE
         11   : 1=IORDY supported
         11   : 1=IORDY supported
         0=IORDY may be supported
         0=IORDY may be supported
         10   : 1=IORDY may be disabled
         10   : 1=IORDY may be disabled
         9   : set to one
         9   : set to one
         8   : set to one
         8   : set to one
         7-0 : retired
         7-0 : retired
       */
       */
      *buf++ = 0x0f00;
      *buf++ = 0x0f00;
 
 
      /*
      /*
         word 50: Capabilities
         word 50: Capabilities
         15  : always cleared to zero
         15  : always cleared to zero
         14  : always set to one
         14  : always set to one
         13-1: reserved
         13-1: reserved
         0   : 1=Device specific standby timer minimum value FIXME
         0   : 1=Device specific standby timer minimum value FIXME
       */
       */
      *buf++ = 0x4000;
      *buf++ = 0x4000;
 
 
      /*
      /*
         word 52-51: obsolete
         word 52-51: obsolete
       */
       */
      buf += 2;
      buf += 2;
 
 
      /*
      /*
         word 53:
         word 53:
         15-3: Reserved
         15-3: Reserved
         2   : 1=value in word 88 is valid
         2   : 1=value in word 88 is valid
         0=value in word 88 is not valid
         0=value in word 88 is not valid
         1   : 1=value in word 64-70 is valid
         1   : 1=value in word 64-70 is valid
         0=value in word 64-70 is not valid
         0=value in word 64-70 is not valid
         0   : 1=value in word 54-58 is valid
         0   : 1=value in word 54-58 is valid
         0=value in word 54-58 is not valid
         0=value in word 54-58 is not valid
       */
       */
      *buf++ = 0x0007;
      *buf++ = 0x0007;
 
 
 
 
      /*
      /*
         word 54: number of current logical cylinders (0-65535)
         word 54: number of current logical cylinders (0-65535)
       */
       */
      if ((tmp = device->conf.size_sect) > 16514064)
      if ((tmp = device->conf.size_sect) > 16514064)
        tmp = 16514064;
        tmp = 16514064;
 
 
      tmp /= (device->internals.heads_per_cylinder +
      tmp /= (device->internals.heads_per_cylinder +
              1) * (device->internals.sectors_per_track);
              1) * (device->internals.sectors_per_track);
      if (tmp > 65535)
      if (tmp > 65535)
        *buf++ = 65535;
        *buf++ = 65535;
      else
      else
        *buf++ = tmp;
        *buf++ = tmp;
 
 
      /*
      /*
         word 55: number of current logical heads, (0-15)
         word 55: number of current logical heads, (0-15)
       */
       */
      *buf++ = device->internals.heads_per_cylinder + 1;
      *buf++ = device->internals.heads_per_cylinder + 1;
 
 
      /*
      /*
         word 56: number of current logical sectors per track (1-255)
         word 56: number of current logical sectors per track (1-255)
       */
       */
      *buf++ = device->internals.sectors_per_track;
      *buf++ = device->internals.sectors_per_track;
 
 
      /*
      /*
         word 58-57: current capacity in sectors
         word 58-57: current capacity in sectors
       */
       */
      tmp = *(buf - 3) * *(buf - 2) * *(buf - 1);
      tmp = *(buf - 3) * *(buf - 2) * *(buf - 1);
      *buf++ = tmp >> 16;
      *buf++ = tmp >> 16;
      *buf++ = tmp & 0xffff;
      *buf++ = tmp & 0xffff;
 
 
      /*
      /*
         word 59:
         word 59:
         15-9: reserved
         15-9: reserved
         8   : 1=multiple sector setting is valid
         8   : 1=multiple sector setting is valid
         7-0 : current setting for number of sectors to be transfered
         7-0 : current setting for number of sectors to be transfered
         per interrupt on a READ/WRITE MULTIPLE command
         per interrupt on a READ/WRITE MULTIPLE command
       */
       */
      *buf++ = 0x0001;          // not really a FIXME
      *buf++ = 0x0001;          // not really a FIXME
 
 
      /*
      /*
         word 60-61: Total number of user addressable sectors (LBA only)
         word 60-61: Total number of user addressable sectors (LBA only)
       */
       */
      *buf++ = device->conf.size_sect;
      *buf++ = device->conf.size_sect;
      *buf++ = device->conf.size_sect >> 16;
      *buf++ = device->conf.size_sect >> 16;
 
 
      /*
      /*
         word 62: obsolete
         word 62: obsolete
       */
       */
      buf++;
      buf++;
 
 
      /* FIXME
      /* FIXME
         word 63: DMA settings
         word 63: DMA settings
         15-11: Reserved
         15-11: Reserved
         10   : 1=Multiword DMA Mode 2 is selected
         10   : 1=Multiword DMA Mode 2 is selected
         0=Multiword DMA Mode 2 is not selected
         0=Multiword DMA Mode 2 is not selected
         9   : 1=Multiword DMA Mode 1 is selected
         9   : 1=Multiword DMA Mode 1 is selected
         0=Multiword DMA Mode 1 is not selected
         0=Multiword DMA Mode 1 is not selected
         8   : 1=Multiword DMA Mode 0 is selected
         8   : 1=Multiword DMA Mode 0 is selected
         0=Multiword DMA Mode 0 is not selected
         0=Multiword DMA Mode 0 is not selected
         7-3 : Reserved
         7-3 : Reserved
         2   : Multiword DMA Mode 2 and below are supported
         2   : Multiword DMA Mode 2 and below are supported
         1   : Multiword DMA Mode 1 and below are supported
         1   : Multiword DMA Mode 1 and below are supported
         0   : Multiword DMA Mode 0 is supported
         0   : Multiword DMA Mode 0 is supported
       */
       */
      *buf = 0;
      *buf = 0;
      if (device->conf.mwdma >= 0)
      if (device->conf.mwdma >= 0)
        *buf |= 0x1;
        *buf |= 0x1;
      if (device->conf.mwdma >= 1)
      if (device->conf.mwdma >= 1)
        *buf |= 0x2;
        *buf |= 0x2;
      if (device->conf.mwdma >= 2)
      if (device->conf.mwdma >= 2)
        *buf |= 0x4;
        *buf |= 0x4;
 
 
      buf++;
      buf++;
 
 
      /*
      /*
         word 64:
         word 64:
         15-8: reserved
         15-8: reserved
         7-0: Advanced PIO modes supported
         7-0: Advanced PIO modes supported
 
 
         7-2: reserved
         7-2: reserved
         1  : PIO mode4 supported
         1  : PIO mode4 supported
         0  : PIO mode3 supported
         0  : PIO mode3 supported
       */
       */
      *buf = 0;
      *buf = 0;
      if (device->conf.pio >= 3)
      if (device->conf.pio >= 3)
        *buf |= 0x1;
        *buf |= 0x1;
      if (device->conf.pio >= 4)
      if (device->conf.pio >= 4)
        *buf |= 0x2;
        *buf |= 0x2;
      buf++;
      buf++;
 
 
      /*
      /*
         word 65: Minimum Multiword DMA transfer cycle time per word (nsec)
         word 65: Minimum Multiword DMA transfer cycle time per word (nsec)
       */
       */
      *buf++ = MIN_MWDMA_CYCLE_TIME;
      *buf++ = MIN_MWDMA_CYCLE_TIME;
 
 
      /*
      /*
         word 66: Manufacturer's recommended Multiword DMA transfer cycle time per word (nsec)
         word 66: Manufacturer's recommended Multiword DMA transfer cycle time per word (nsec)
       */
       */
      *buf++ = RECOMMENDED_MWDMA_CYCLE_TIME;
      *buf++ = RECOMMENDED_MWDMA_CYCLE_TIME;
 
 
 
 
      /*
      /*
         word 67: Minimum PIO transfer cycle time per word (nsec), without IORDY flow control
         word 67: Minimum PIO transfer cycle time per word (nsec), without IORDY flow control
       */
       */
      *buf++ = MIN_PIO_CYCLE_TIME_NO_IORDY;
      *buf++ = MIN_PIO_CYCLE_TIME_NO_IORDY;
 
 
      /*
      /*
         word 68: Minimum PIO transfer cycle time per word (nsec), with IORDY flow control
         word 68: Minimum PIO transfer cycle time per word (nsec), with IORDY flow control
       */
       */
      *buf++ = MIN_PIO_CYCLE_TIME_IORDY;
      *buf++ = MIN_PIO_CYCLE_TIME_IORDY;
 
 
      /*
      /*
         word 69-70: reserved for future command overlap and queueing
         word 69-70: reserved for future command overlap and queueing
         71-74: reserved for IDENTIFY PACKET DEVICE command
         71-74: reserved for IDENTIFY PACKET DEVICE command
       */
       */
      buf += 6;
      buf += 6;
 
 
      /*
      /*
         word 75: Queue depth
         word 75: Queue depth
         15-5: reserved
         15-5: reserved
         4-0: queue depth -1
         4-0: queue depth -1
       */
       */
      *buf++ = SUPPORT_READ_WRITE_DMA_QUEUED ? QUEUE_DEPTH : 0x0000;
      *buf++ = SUPPORT_READ_WRITE_DMA_QUEUED ? QUEUE_DEPTH : 0x0000;
 
 
      /*
      /*
         word 76-79: reserved
         word 76-79: reserved
       */
       */
      buf += 4;
      buf += 4;
 
 
      /*
      /*
         word 80: MAJOR ATA version
         word 80: MAJOR ATA version
         We simply report that we do not report a version
         We simply report that we do not report a version
 
 
         You can also set bits 5-2 to indicate compliancy to
         You can also set bits 5-2 to indicate compliancy to
         ATA revisions 5-2 (1 & 0 are obsolete)
         ATA revisions 5-2 (1 & 0 are obsolete)
       */
       */
      *buf++ = 0x0000;
      *buf++ = 0x0000;
 
 
      /*
      /*
         word 81: MINOR ATA version
         word 81: MINOR ATA version
         We report ATA/ATAPI-5 T13 1321D revision 3 (0x13)
         We report ATA/ATAPI-5 T13 1321D revision 3 (0x13)
       */
       */
      *buf++ = 0x0013;
      *buf++ = 0x0013;
 
 
      /*
      /*
         word 82: Command set supported
         word 82: Command set supported
       */
       */
      *buf++ = 0 << 15 | /* obsolete        */
      *buf++ = 0 << 15 | /* obsolete        */
        SUPPORT_NOP_CMD << 14 | SUPPORT_READ_BUFFER_CMD << 13 | SUPPORT_WRITE_BUFFER_CMD << 12 | 0 << 11 |       /* obsolete        */
        SUPPORT_NOP_CMD << 14 | SUPPORT_READ_BUFFER_CMD << 13 | SUPPORT_WRITE_BUFFER_CMD << 12 | 0 << 11 |       /* obsolete        */
        SUPPORT_HOST_PROTECTED_AREA << 10 | SUPPORT_DEVICE_RESET_CMD << 9 | SUPPORT_SERVICE_INTERRUPT << 8 | SUPPORT_RELEASE_INTERRUPT << 7 | SUPPORT_LOOKAHEAD << 6 | SUPPORT_WRITE_CACHE << 5 | 0 << 4 |       /* cleared to zero */
        SUPPORT_HOST_PROTECTED_AREA << 10 | SUPPORT_DEVICE_RESET_CMD << 9 | SUPPORT_SERVICE_INTERRUPT << 8 | SUPPORT_RELEASE_INTERRUPT << 7 | SUPPORT_LOOKAHEAD << 6 | SUPPORT_WRITE_CACHE << 5 | 0 << 4 |       /* cleared to zero */
        SUPPORT_POWER_MANAGEMENT << 3 |
        SUPPORT_POWER_MANAGEMENT << 3 |
        SUPPORT_REMOVABLE_MEDIA << 2 |
        SUPPORT_REMOVABLE_MEDIA << 2 |
        SUPPORT_SECURITY_MODE << 1 | SUPPORT_SMART << 0;
        SUPPORT_SECURITY_MODE << 1 | SUPPORT_SMART << 0;
 
 
      /*
      /*
         word 83: Command set supported
         word 83: Command set supported
       */
       */
      *buf++ = 0 << 15 | /* cleared to zero */
      *buf++ = 0 << 15 | /* cleared to zero */
        1 << 14 |               /* set to one      */
        1 << 14 |               /* set to one      */
        0 << 9 |         /* reserved        */
        0 << 9 |         /* reserved        */
        SUPPORT_SET_MAX << 8 | 0 << 7 |  /* reserved for    */
        SUPPORT_SET_MAX << 8 | 0 << 7 |  /* reserved for    */
        /* project 1407DT  */
        /* project 1407DT  */
        SET_FEATURES_REQUIRED_AFTER_POWER_UP << 6 |
        SET_FEATURES_REQUIRED_AFTER_POWER_UP << 6 |
        SUPPORT_POWER_UP_IN_STANDBY_MODE << 5 |
        SUPPORT_POWER_UP_IN_STANDBY_MODE << 5 |
        SUPPORT_REMOVABLE_MEDIA_NOTIFICATION << 4 |
        SUPPORT_REMOVABLE_MEDIA_NOTIFICATION << 4 |
        SUPPORT_APM << 3 |
        SUPPORT_APM << 3 |
        SUPPORT_CFA << 2 |
        SUPPORT_CFA << 2 |
        SUPPORT_READ_WRITE_DMA_QUEUED << 1 | SUPPORT_DOWNLOAD_MICROCODE << 0;
        SUPPORT_READ_WRITE_DMA_QUEUED << 1 | SUPPORT_DOWNLOAD_MICROCODE << 0;
 
 
      /*
      /*
         word 84: Command set/feature supported
         word 84: Command set/feature supported
       */
       */
      *buf++ = 0 << 15 | /* cleared to zero */
      *buf++ = 0 << 15 | /* cleared to zero */
        1 << 14                 /* set to one      */
        1 << 14                 /* set to one      */
        ;                       /* 0-13 reserved   */
        ;                       /* 0-13 reserved   */
 
 
      /*
      /*
         word 85: Command set enabled FIXME
         word 85: Command set enabled FIXME
       */
       */
      *buf++ = 0 << 15 | /* obsolete        */
      *buf++ = 0 << 15 | /* obsolete        */
        SUPPORT_NOP_CMD << 14 | SUPPORT_READ_BUFFER_CMD << 13 | SUPPORT_WRITE_BUFFER_CMD << 12 | 0 << 11 |       /* obsolete        */
        SUPPORT_NOP_CMD << 14 | SUPPORT_READ_BUFFER_CMD << 13 | SUPPORT_WRITE_BUFFER_CMD << 12 | 0 << 11 |       /* obsolete        */
        SUPPORT_HOST_PROTECTED_AREA << 10 | SUPPORT_DEVICE_RESET_CMD << 9 | SUPPORT_SERVICE_INTERRUPT << 8 | SUPPORT_RELEASE_INTERRUPT << 7 | SUPPORT_LOOKAHEAD << 6 | SUPPORT_WRITE_CACHE << 5 | 0 << 4 |       /* cleared to zero */
        SUPPORT_HOST_PROTECTED_AREA << 10 | SUPPORT_DEVICE_RESET_CMD << 9 | SUPPORT_SERVICE_INTERRUPT << 8 | SUPPORT_RELEASE_INTERRUPT << 7 | SUPPORT_LOOKAHEAD << 6 | SUPPORT_WRITE_CACHE << 5 | 0 << 4 |       /* cleared to zero */
        SUPPORT_POWER_MANAGEMENT << 3 |
        SUPPORT_POWER_MANAGEMENT << 3 |
        SUPPORT_REMOVABLE_MEDIA << 2 |
        SUPPORT_REMOVABLE_MEDIA << 2 |
        SUPPORT_SECURITY_MODE << 1 | SUPPORT_SMART << 0;
        SUPPORT_SECURITY_MODE << 1 | SUPPORT_SMART << 0;
 
 
      /*
      /*
         word 86: Command set enables
         word 86: Command set enables
       */
       */
      *buf++ = 0 << 9 |          /* 15-9 reserved   */
      *buf++ = 0 << 9 |          /* 15-9 reserved   */
        SUPPORT_SET_MAX << 8 | 0 << 7 |  /* reserved for    */
        SUPPORT_SET_MAX << 8 | 0 << 7 |  /* reserved for    */
        /* project 1407DT  */
        /* project 1407DT  */
        SET_FEATURES_REQUIRED_AFTER_POWER_UP << 6 |
        SET_FEATURES_REQUIRED_AFTER_POWER_UP << 6 |
        SUPPORT_POWER_UP_IN_STANDBY_MODE << 5 |
        SUPPORT_POWER_UP_IN_STANDBY_MODE << 5 |
        SUPPORT_REMOVABLE_MEDIA_NOTIFICATION << 4 |
        SUPPORT_REMOVABLE_MEDIA_NOTIFICATION << 4 |
        SUPPORT_APM << 3 |
        SUPPORT_APM << 3 |
        SUPPORT_CFA << 2 |
        SUPPORT_CFA << 2 |
        SUPPORT_READ_WRITE_DMA_QUEUED << 1 | SUPPORT_DOWNLOAD_MICROCODE << 0;
        SUPPORT_READ_WRITE_DMA_QUEUED << 1 | SUPPORT_DOWNLOAD_MICROCODE << 0;
 
 
      /*
      /*
         word 87: Command set/feature supported
         word 87: Command set/feature supported
       */
       */
      *buf++ = 0 << 15 | /* cleared to zero */
      *buf++ = 0 << 15 | /* cleared to zero */
        1 << 14                 /* set to one      */
        1 << 14                 /* set to one      */
        ;                       /* 0-13 reserved   */
        ;                       /* 0-13 reserved   */
 
 
      /*
      /*
         word 88: UltraDMA section
         word 88: UltraDMA section
         15-13: reserved
         15-13: reserved
         12   : 1=UltraDMA Mode 4 is selected
         12   : 1=UltraDMA Mode 4 is selected
         0=UltraDMA Mode 4 is not selected
         0=UltraDMA Mode 4 is not selected
         10   : 1=UltraDMA Mode 3 is selected
         10   : 1=UltraDMA Mode 3 is selected
         0=UltraDMA Mode 3 is not selected
         0=UltraDMA Mode 3 is not selected
         10   : 1=UltraDMA Mode 2 is selected
         10   : 1=UltraDMA Mode 2 is selected
         0=UltraDMA Mode 2 is not selected
         0=UltraDMA Mode 2 is not selected
         9   : 1=UltraDMA Mode 1 is selected
         9   : 1=UltraDMA Mode 1 is selected
         0=UltraDMA Mode 1 is not selected
         0=UltraDMA Mode 1 is not selected
         8   : 1=UltraDMA Mode 0 is selected
         8   : 1=UltraDMA Mode 0 is selected
         0=UltraDMA Mode 0 is not selected
         0=UltraDMA Mode 0 is not selected
         7-5 : Reserved
         7-5 : Reserved
         4   : UltraDMA Mode 4 and below are supported
         4   : UltraDMA Mode 4 and below are supported
         3   : UltraDMA Mode 3 and below are supported
         3   : UltraDMA Mode 3 and below are supported
         2   : UltraDMA Mode 2 and below are supported
         2   : UltraDMA Mode 2 and below are supported
         1   : UltraDMA Mode 1 and below are supported
         1   : UltraDMA Mode 1 and below are supported
         0   : UltraDMA Mode 0 is supported
         0   : UltraDMA Mode 0 is supported
 
 
         Because the OCIDEC cores currently do not support
         Because the OCIDEC cores currently do not support
         UltraDMA we set all bits to zero
         UltraDMA we set all bits to zero
       */
       */
      *buf++ = 0;
      *buf++ = 0;
 
 
      /*
      /*
         word 89: Security sector erase unit completion time
         word 89: Security sector erase unit completion time
 
 
         For now we report a 'value not specified'.
         For now we report a 'value not specified'.
       */
       */
      *buf++ = 0x0000;          // not really a FIXME
      *buf++ = 0x0000;          // not really a FIXME
 
 
      /*
      /*
         word 90: Enhanced security erase completion time
         word 90: Enhanced security erase completion time
 
 
         For now we report a 'value not specified'.
         For now we report a 'value not specified'.
       */
       */
      *buf++ = 0x0000;          // not really a FIXME
      *buf++ = 0x0000;          // not really a FIXME
 
 
      /*
      /*
         word 91: Current advanced power management value
         word 91: Current advanced power management value
 
 
         For now set it to zero.
         For now set it to zero.
       */
       */
      *buf++ = 0x0000;          // FIXME
      *buf++ = 0x0000;          // FIXME
 
 
      /*
      /*
         word 92: Master Password Revision Code.
         word 92: Master Password Revision Code.
         We simply report that we do not support this.
         We simply report that we do not support this.
       */
       */
      *buf++ = 0x0000;
      *buf++ = 0x0000;
 
 
      /*
      /*
         word 93: Hardware reset result
         word 93: Hardware reset result
       */
       */
      if (device->internals.dev)
      if (device->internals.dev)
        {
        {
          /* this is device1, clear device0 bits                                         */
          /* this is device1, clear device0 bits                                         */
          *buf++ = 0 << 15 | 1 << 14 | 0 << 13 |  /* CBLIBD level (1=Vih, 0=Vil)               */
          *buf++ = 0 << 15 | 1 << 14 | 0 << 13 |  /* CBLIBD level (1=Vih, 0=Vil)               */
            /* 12-8 Device 1 hardware reset result       */
            /* 12-8 Device 1 hardware reset result       */
            0 << 12 |            /* reserved                                  */
            0 << 12 |            /* reserved                                  */
            device->sigs.pdiago << 11 | /* 1: Device1 did assert PDIAG               */
            device->sigs.pdiago << 11 | /* 1: Device1 did assert PDIAG               */
            /* 0: Device1 did not assert PDIAG           */
            /* 0: Device1 did not assert PDIAG           */
            3 << 9 |            /* Device1 determined device number by       */
            3 << 9 |            /* Device1 determined device number by       */
            /* 00: reserved                              */
            /* 00: reserved                              */
            /* 01: a jumper was used                     */
            /* 01: a jumper was used                     */
            /* 10: the CSEL signal was used              */
            /* 10: the CSEL signal was used              */
            /* 11: some other or unknown method was used */
            /* 11: some other or unknown method was used */
            1 << 8              /* set to one                                */
            1 << 8              /* set to one                                */
            ;
            ;
        }
        }
      else
      else
        {                       /* FIXME bit 6 */
        {                       /* FIXME bit 6 */
          /* this is device0, clear device1 bits                                         */
          /* this is device0, clear device1 bits                                         */
          *buf++ = 0 << 7 |      /* reserved                                  */
          *buf++ = 0 << 7 |      /* reserved                                  */
            0 << 6 |             /* 1: Device0 responds for device 1          */
            0 << 6 |             /* 1: Device0 responds for device 1          */
            /* 0: Device0 does not respond for device1   */
            /* 0: Device0 does not respond for device1   */
            device->sigs.daspi << 5 |   /* 1: Device0 did detected DASP assertion    */
            device->sigs.daspi << 5 |   /* 1: Device0 did detected DASP assertion    */
            /* 0: Device0 did not detect DASP assertion  */
            /* 0: Device0 did not detect DASP assertion  */
            device->sigs.pdiagi << 4 |  /* Device0 did detect PDIAG assertion        */
            device->sigs.pdiagi << 4 |  /* Device0 did detect PDIAG assertion        */
            /* Device0 did not detect PDIAG assertion    */
            /* Device0 did not detect PDIAG assertion    */
            1 << 3 |            /* Device0 did pass diagnostics              */
            1 << 3 |            /* Device0 did pass diagnostics              */
            3 << 1 |            /* Device0 determined device number by       */
            3 << 1 |            /* Device0 determined device number by       */
            /* 00: reserved                              */
            /* 00: reserved                              */
            /* 01: a jumper was used                     */
            /* 01: a jumper was used                     */
            /* 10: the CSEL signal was used              */
            /* 10: the CSEL signal was used              */
            /* 11: some other or unknown method was used */
            /* 11: some other or unknown method was used */
            1 << 0               /* set to one                                */
            1 << 0               /* set to one                                */
            ;
            ;
        }
        }
 
 
      /*
      /*
         word 94-126: Reserved
         word 94-126: Reserved
       */
       */
      buf += 33;
      buf += 33;
 
 
      /*
      /*
         word 127: Removable Media Status Notification feature set support
         word 127: Removable Media Status Notification feature set support
         15-2: reserved
         15-2: reserved
         1-0: 00 Removable media Status Notification not supported
         1-0: 00 Removable media Status Notification not supported
         01 Removable media Status Notification supported
         01 Removable media Status Notification supported
         10 reserved
         10 reserved
         11 reserved
         11 reserved
       */
       */
      *buf++ = SUPPORT_REMOVABLE_MEDIA_NOTIFICATION;
      *buf++ = SUPPORT_REMOVABLE_MEDIA_NOTIFICATION;
 
 
      /*
      /*
         word 128: Security status
         word 128: Security status
         15-9: reserved
         15-9: reserved
         8   : Security level, 0=high, 1=maximum
         8   : Security level, 0=high, 1=maximum
         7-6 : reserved
         7-6 : reserved
         5   : 1=enhanced security erase supported
         5   : 1=enhanced security erase supported
         4   : 1=security count expired
         4   : 1=security count expired
         3   : 1=security frozen
         3   : 1=security frozen
         2   : 1=security locked
         2   : 1=security locked
         1   : 1=security enabled
         1   : 1=security enabled
         0   : security supported
         0   : security supported
 
 
         for now we do not support security, set is to zero
         for now we do not support security, set is to zero
       */
       */
      *buf++ = 0;
      *buf++ = 0;
 
 
      /*
      /*
         word 129-159: Vendor specific
         word 129-159: Vendor specific
       */
       */
      buf += 31;
      buf += 31;
 
 
      /*
      /*
         word 160: CFA power mode 1
         word 160: CFA power mode 1
         15  : Word 160 supported
         15  : Word 160 supported
         14  : reserved
         14  : reserved
         13  : CFA power mode 1 is required for one or more commands
         13  : CFA power mode 1 is required for one or more commands
         12  : CFA power mode 1 disabled
         12  : CFA power mode 1 disabled
         11-0: Maximum current in mA
         11-0: Maximum current in mA
       */
       */
      *buf++ = 0;
      *buf++ = 0;
 
 
      /*
      /*
         word 161-175: Reserved for the CompactFLASH Association
         word 161-175: Reserved for the CompactFLASH Association
       */
       */
      buf += 15;
      buf += 15;
 
 
      /*
      /*
         word 176-254: reserved
         word 176-254: reserved
       */
       */
      buf += 79;
      buf += 79;
 
 
      /*
      /*
         word 255: Integrity word
         word 255: Integrity word
         15-8: Checksum
         15-8: Checksum
         7-0 : Signature
         7-0 : Signature
       */
       */
      // set signature to indicate valid checksum
      // set signature to indicate valid checksum
      *buf = 0x00a5;
      *buf = 0x00a5;
 
 
      // calculate checksum
      // calculate checksum
      chksum = 0;
      chksum = 0;
      for (n = 0; n < 511; n++)
      for (n = 0; n < 511; n++)
        chksum += *chksum_buf++;
        chksum += *chksum_buf++;
 
 
      *buf = ((0 - chksum) << 8) | 0x00a5;
      *buf = ((0 - chksum) << 8) | 0x00a5;
 
 
      /* set status register bits                                       */
      /* set status register bits                                       */
      device->regs.status = ATA_SR_DRDY | ATA_SR_DRQ;
      device->regs.status = ATA_SR_DRDY | ATA_SR_DRQ;
    }
    }
}
}
 
 
 
 
/*
/*
  A T A _ I N I T I A L I Z E _ D E V I C E _ P A R A M E T E R S
  A T A _ I N I T I A L I Z E _ D E V I C E _ P A R A M E T E R S
*/
*/
static void
static void
ata_initialize_device_parameters_cmd (struct ata_device *device)
ata_initialize_device_parameters_cmd (struct ata_device *device)
{
{
  device->internals.sectors_per_track = device->regs.sector_count;
  device->internals.sectors_per_track = device->regs.sector_count;
  device->internals.heads_per_cylinder = device->regs.device_head & ATA_DHR_H;
  device->internals.heads_per_cylinder = device->regs.device_head & ATA_DHR_H;
 
 
  /* set status register bits                                         */
  /* set status register bits                                         */
  device->regs.status = ATA_SR_BSY | ATA_SR_DRDY;
  device->regs.status = ATA_SR_BSY | ATA_SR_DRDY;
}
}
 
 
 
 
/*
/*
  A T A _ R E A D _ S E C T O R S
  A T A _ R E A D _ S E C T O R S
*/
*/
static void
static void
ata_read_sectors_cmd (struct ata_device *device)
ata_read_sectors_cmd (struct ata_device *device)
{
{
  size_t sector_count;
  size_t sector_count;
  uint32_t lba;
  uint32_t lba;
 
 
  /* check if this is a NON-PACKET device                             */
  /* check if this is a NON-PACKET device                             */
  if (device->conf.packet)
  if (device->conf.packet)
    {
    {
      /*
      /*
         This is a PACKET device.
         This is a PACKET device.
         Respond by placing PACKET Command feature set signature in block registers.
         Respond by placing PACKET Command feature set signature in block registers.
         Abort command.
         Abort command.
       */
       */
      ata_set_device_signature (device, 1);
      ata_set_device_signature (device, 1);
      device->regs.status = ATA_SR_ERR | ATA_SR_DRDY;
      device->regs.status = ATA_SR_ERR | ATA_SR_DRDY;
      device->regs.error = ATA_ERR_ABT;
      device->regs.error = ATA_ERR_ABT;
      return;
      return;
    }
    }
 
 
  /* get the sector count                                           */
  /* get the sector count                                           */
  if (device->regs.sector_count == 0)
  if (device->regs.sector_count == 0)
    sector_count = 256;
    sector_count = 256;
  else
  else
    sector_count = device->regs.sector_count;
    sector_count = device->regs.sector_count;
 
 
  lba = ata_calc_lba (device);
  lba = ata_calc_lba (device);
 
 
  /* check if sector within bounds                                  */
  /* check if sector within bounds                                  */
  if (lba >= device->conf.size_sect)
  if (lba >= device->conf.size_sect)
    {
    {
      /* invalid sector address                                     */
      /* invalid sector address                                     */
      /* set the status & error registers                           */
      /* set the status & error registers                           */
      device->regs.status = ATA_SR_DRDY | ATA_SR_ERR;
      device->regs.status = ATA_SR_DRDY | ATA_SR_ERR;
      device->regs.error = ATA_ERR_IDNF;
      device->regs.error = ATA_ERR_IDNF;
      return;
      return;
    }
    }
 
 
  /* go ahead, read the bytestream                              */
  /* go ahead, read the bytestream                              */
  lba *= BYTES_PER_SECTOR;
  lba *= BYTES_PER_SECTOR;
 
 
  device->internals.lba = lba;
  device->internals.lba = lba;
  device->internals.nr_sect = sector_count;
  device->internals.nr_sect = sector_count;
  device->internals.end_t_func = ata_read_sect;
  device->internals.end_t_func = ata_read_sect;
 
 
  ata_read_sect (device);
  ata_read_sect (device);
}
}
 
 
 
 
 
 
/*
/*
  A T A _ R E A D _ N A T I V E _ M A X _ A D D R
  A T A _ R E A D _ N A T I V E _ M A X _ A D D R
*/
*/
static void
static void
ata_read_native_max_addr (struct ata_device *dev)
ata_read_native_max_addr (struct ata_device *dev)
{
{
  // FIXME: Left shift????
  // FIXME: Left shift????
  ata_set_sect (dev, dev->conf.size << 11);
  ata_set_sect (dev, dev->conf.size << 11);
 
 
  dev->regs.status = ATA_SR_DRDY | ATA_SR_BSY;
  dev->regs.status = ATA_SR_DRDY | ATA_SR_BSY;
}
}
 
 
/*
/*
  A T A _ W R I T E _ S E C T O R S
  A T A _ W R I T E _ S E C T O R S
*/
*/
static void
static void
ata_write_sectors (struct ata_device *dev)
ata_write_sectors (struct ata_device *dev)
{
{
  size_t sector_count;
  size_t sector_count;
  uint32_t lba;
  uint32_t lba;
 
 
  if (dev->conf.packet)
  if (dev->conf.packet)
    {
    {
      ata_set_device_signature (dev, 1);
      ata_set_device_signature (dev, 1);
      dev->regs.status = ATA_SR_ERR | ATA_SR_DRDY;
      dev->regs.status = ATA_SR_ERR | ATA_SR_DRDY;
      dev->regs.error = ATA_ERR_ABT;
      dev->regs.error = ATA_ERR_ABT;
      return;
      return;
    }
    }
 
 
  /* get the sector count                                           */
  /* get the sector count                                           */
  if (dev->regs.sector_count == 0)
  if (dev->regs.sector_count == 0)
    sector_count = 256;
    sector_count = 256;
  else
  else
    sector_count = dev->regs.sector_count;
    sector_count = dev->regs.sector_count;
 
 
  lba = ata_calc_lba (dev);
  lba = ata_calc_lba (dev);
 
 
  /* check if sector within bounds                                  */
  /* check if sector within bounds                                  */
  if (lba >= dev->conf.size_sect)
  if (lba >= dev->conf.size_sect)
    {
    {
      /* invalid sector address                                     */
      /* invalid sector address                                     */
      /* set the status & error registers                           */
      /* set the status & error registers                           */
      dev->regs.status = ATA_SR_DRDY | ATA_SR_ERR;
      dev->regs.status = ATA_SR_DRDY | ATA_SR_ERR;
      dev->regs.error = ATA_ERR_IDNF;
      dev->regs.error = ATA_ERR_IDNF;
      return;
      return;
    }
    }
 
 
  dev->internals.lba = lba * BYTES_PER_SECTOR;
  dev->internals.lba = lba * BYTES_PER_SECTOR;
  dev->internals.nr_sect = sector_count;
  dev->internals.nr_sect = sector_count;
 
 
  dev->internals.dbuf_cnt = BYTES_PER_SECTOR / 2;       //Words, not bytes
  dev->internals.dbuf_cnt = BYTES_PER_SECTOR / 2;       //Words, not bytes
  dev->internals.dbuf_ptr = dev->internals.dbuf;
  dev->internals.dbuf_ptr = dev->internals.dbuf;
 
 
  dev->regs.status = ATA_SR_BSY | ATA_SR_DRDY | ATA_SR_DRQ;
  dev->regs.status = ATA_SR_BSY | ATA_SR_DRDY | ATA_SR_DRQ;
  dev->internals.end_t_func = ata_write_sect;
  dev->internals.end_t_func = ata_write_sect;
}
}
 
 
/*
/*
  A T A _ S E T _ F E A T U R E S
  A T A _ S E T _ F E A T U R E S
*/
*/
static void
static void
ata_set_features (struct ata_device *dev)
ata_set_features (struct ata_device *dev)
{
{
  switch (dev->regs.features)
  switch (dev->regs.features)
    {
    {
    case SET_TRANSFER_MODE_SECTOR_COUNT_REG:
    case SET_TRANSFER_MODE_SECTOR_COUNT_REG:
      /* FIXME: I don't have a clue as to what to do with this... */
      /* FIXME: I don't have a clue as to what to do with this... */
      switch (dev->regs.sector_count >> 3)
      switch (dev->regs.sector_count >> 3)
        {
        {
        case 0:          /* Set default */
        case 0:          /* Set default */
          break;
          break;
        case 1:         /* Set PIO mode */
        case 1:         /* Set PIO mode */
          break;
          break;
        case 4:         /* Set DMA mode */
        case 4:         /* Set DMA mode */
          /* FIXME */
          /* FIXME */
          fprintf (stderr, "Fixme: Set DMA mode to %d\n",
          fprintf (stderr, "Fixme: Set DMA mode to %d\n",
                   dev->regs.sector_count & 0x7);
                   dev->regs.sector_count & 0x7);
          break;
          break;
        case 8:         /* Set UDMA mode */
        case 8:         /* Set UDMA mode */
          /* FIXME */
          /* FIXME */
          fprintf (stderr, "Fixme: Set UDMA mode to %d\n",
          fprintf (stderr, "Fixme: Set UDMA mode to %d\n",
                   dev->regs.sector_count & 0x7);
                   dev->regs.sector_count & 0x7);
          break;
          break;
        }
        }
      dev->regs.status = ATA_SR_DSC | ATA_SR_DRDY | ATA_SR_BSY;
      dev->regs.status = ATA_SR_DSC | ATA_SR_DRDY | ATA_SR_BSY;
      break;
      break;
    default:
    default:
      dev->regs.error = ATA_ERR_ABT;
      dev->regs.error = ATA_ERR_ABT;
      dev->regs.status = ATA_SR_ERR | ATA_SR_BSY | ATA_SR_DRDY;
      dev->regs.status = ATA_SR_ERR | ATA_SR_BSY | ATA_SR_DRDY;
      /* FIXME */
      /* FIXME */
      fprintf (stderr, "Fixme: Unknown set features sub-command %x\n",
      fprintf (stderr, "Fixme: Unknown set features sub-command %x\n",
               dev->regs.features);
               dev->regs.features);
    }
    }
}
}
 
 
 
 
int
int
ata_device_execute_cmd (struct ata_device *device)
ata_device_execute_cmd (struct ata_device *device)
{
{
  /* execute the commands */
  /* execute the commands */
  switch (device->regs.command)
  switch (device->regs.command)
    {
    {
    case DEVICE_RESET:
    case DEVICE_RESET:
      ata_device_reset_cmd (device);
      ata_device_reset_cmd (device);
      SCHED_ADD (ata_cmd_complete, device, 4000000);
      SCHED_ADD (ata_cmd_complete, device, 4000000);
      return 0;
      return 0;
 
 
    case EXECUTE_DEVICE_DIAGNOSTICS:
    case EXECUTE_DEVICE_DIAGNOSTICS:
      ata_execute_device_diagnostics_cmd (device);
      ata_execute_device_diagnostics_cmd (device);
      SCHED_ADD (ata_cmd_complete, device, 4000000);
      SCHED_ADD (ata_cmd_complete, device, 4000000);
      return 0;
      return 0;
 
 
    case IDENTIFY_DEVICE:
    case IDENTIFY_DEVICE:
      ata_identify_device_cmd (device);
      ata_identify_device_cmd (device);
      /* FIXME: This should generate an interrupt, but linux is abit broken so
      /* FIXME: This should generate an interrupt, but linux is abit broken so
       * it doesn't happen */
       * it doesn't happen */
      //SCHED_ADD(ata_cmd_complete, device, 40000);
      //SCHED_ADD(ata_cmd_complete, device, 40000);
      return 0;
      return 0;
 
 
    case INITIALIZE_DEVICE_PARAMETERS:
    case INITIALIZE_DEVICE_PARAMETERS:
      ata_initialize_device_parameters_cmd (device);
      ata_initialize_device_parameters_cmd (device);
      SCHED_ADD (ata_cmd_complete, device, 400000);
      SCHED_ADD (ata_cmd_complete, device, 400000);
      return 0;
      return 0;
 
 
    case READ_SECTORS:
    case READ_SECTORS:
      ata_read_sectors_cmd (device);
      ata_read_sectors_cmd (device);
      /* PIO-in command -- Doesn't interrupt on completion */
      /* PIO-in command -- Doesn't interrupt on completion */
      return 0;
      return 0;
 
 
    case READ_NATIVE_MAX_ADDRESS:
    case READ_NATIVE_MAX_ADDRESS:
      ata_read_native_max_addr (device);
      ata_read_native_max_addr (device);
      SCHED_ADD (ata_cmd_complete, device, 40000);
      SCHED_ADD (ata_cmd_complete, device, 40000);
      return 0;
      return 0;
 
 
    case WRITE_SECTORS:
    case WRITE_SECTORS:
      ata_write_sectors (device);
      ata_write_sectors (device);
      SCHED_ADD (ata_cmd_complete, device, 40000);
      SCHED_ADD (ata_cmd_complete, device, 40000);
      return 0;
      return 0;
 
 
    case SET_FEATURES:
    case SET_FEATURES:
      ata_set_features (device);
      ata_set_features (device);
      SCHED_ADD (ata_cmd_complete, device, 4000);
      SCHED_ADD (ata_cmd_complete, device, 4000);
      return 0;
      return 0;
 
 
    default:
    default:
      device->regs.error = ATA_ERR_ABT;
      device->regs.error = ATA_ERR_ABT;
      device->regs.status = ATA_SR_ERR | ATA_SR_BSY | ATA_SR_DRDY;
      device->regs.status = ATA_SR_ERR | ATA_SR_BSY | ATA_SR_DRDY;
      /* FIXME */
      /* FIXME */
      fprintf (stderr, "Fixme: Unknown command %x\n", device->regs.command);
      fprintf (stderr, "Fixme: Unknown command %x\n", device->regs.command);
      SCHED_ADD (ata_cmd_complete, device, 40000);
      SCHED_ADD (ata_cmd_complete, device, 40000);
      return -1;
      return -1;
    }
    }
}
}
 
 

powered by: WebSVN 2.1.0

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