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

Subversion Repositories or1k

[/] [or1k/] [tags/] [stable_0_2_0_rc3/] [or1ksim/] [peripheral/] [atadevice_cmdi.c] - Diff between revs 1648 and 1765

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

Rev 1648 Rev 1765
/*
/*
    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
 
 
    This file is part of OpenRISC 1000 Architectural Simulator
    This file is part of OpenRISC 1000 Architectural Simulator
 
 
    This program is free software; you can redistribute it and/or modify
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version
    (at your option) any later version
 
 
    This program is distributed in the hope that it will be useful,
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    GNU General Public License for more details.
 
 
    You should have received a copy of the GNU General Public License
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
*/
 
 
/*
/*
 For fun, count the number of FIXMEs :-(
 For fun, count the number of FIXMEs :-(
*/
*/
 
 
#include <string.h>
#include <string.h>
 
 
#include "atadevice.h"
#include "atadevice.h"
#include "atadevice_cmdi.h"
#include "atadevice_cmdi.h"
#include "atacmd.h"
#include "atacmd.h"
 
 
#include "debug.h"
#include "debug.h"
 
 
DEFAULT_DEBUG_CHANNEL(ata);
DEFAULT_DEBUG_CHANNEL(ata);
 
 
int ata_device_execute_cmd(ata_device *device)
int ata_device_execute_cmd(ata_device *device)
{
{
  /*display debug information                                         */
  /*display debug information                                         */
  TRACE("ata_device_execute_command called with command = 0x%02X\n",
  TRACE("ata_device_execute_command called with command = 0x%02X\n",
        device->regs.command);
        device->regs.command);
 
 
  /* 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);
         return 0;
         return 0;
 
 
      case EXECUTE_DEVICE_DIAGNOSTICS :
      case EXECUTE_DEVICE_DIAGNOSTICS :
        ata_execute_device_diagnostics_cmd(device);
        ata_execute_device_diagnostics_cmd(device);
        return 0;
        return 0;
 
 
      case IDENTIFY_DEVICE :
      case IDENTIFY_DEVICE :
        ata_identify_device_cmd(device);
        ata_identify_device_cmd(device);
        return 0;
        return 0;
 
 
      case INITIALIZE_DEVICE_PARAMETERS :
      case INITIALIZE_DEVICE_PARAMETERS :
        ata_initialize_device_parameters_cmd(device);
        ata_initialize_device_parameters_cmd(device);
        return 0;
        return 0;
 
 
      case READ_SECTORS :
      case READ_SECTORS :
        ata_read_sectors_cmd(device);
        ata_read_sectors_cmd(device);
 
 
      default :
      default :
        return -1;
        return -1;
  }
  }
}
}
 
 
 
 
 
 
/*
/*
  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)
*/
*/
void ata_set_device_signature(ata_device *device, int signature)
void ata_set_device_signature(ata_device *device, int signature)
{
{
    if (signature)
    if (signature)
    {
    {
      /* 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 _ 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
*/
*/
void ata_device_reset_cmd(ata_device *device)
void ata_device_reset_cmd(ata_device *device)
{
{
  /* print debug information                                          */
  /* print debug information                                          */
  TRACE("executing command 'device reset'\n");
  TRACE("executing command 'device reset'\n");
 
 
  if (!device->packet)
  if (!device->packet)
      WARN("executing DEVICE_RESET on non-packet device.");
      WARN("executing DEVICE_RESET on non-packet device.");
 
 
  ata_execute_device_diagnostics_cmd(device);
  ata_execute_device_diagnostics_cmd(device);
}
}
 
 
 
 
/*
/*
  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 ata_execute_device_diagnostics_cmd(ata_device *device)
void ata_execute_device_diagnostics_cmd(ata_device *device)
{
{
  /* print debug information                                          */
  /* print debug information                                          */
  TRACE("executing command 'execute_device_diagnostics'\n");
  TRACE("executing command 'execute_device_diagnostics'\n");
 
 
  /* 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->packet)
  if (device->packet)
  {
  {
    /* place PACKET command feature set signature in register block   */
    /* place PACKET command feature set signature in register block   */
    ata_set_device_signature(device, PACKET_SIGNATURE);
    ata_set_device_signature(device, PACKET_SIGNATURE);
 
 
    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, !PACKET_SIGNATURE);
    ata_set_device_signature(device, !PACKET_SIGNATURE);
 
 
    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 _ 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
*/
*/
void ata_identify_device_cmd(ata_device *device)
void ata_identify_device_cmd(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;
 
 
  /* print debug information                                          */
  /* print debug information                                          */
  TRACE("ata_device executing command 'identify device'\n");
  TRACE("ata_device executing command 'identify device'\n");
 
 
  /* 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;
 
 
  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->packet)
  if (device->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.
    */
    */
    TRACE("'identify_device' command: This is a PACKET device\n");
    TRACE("'identify_device' command: This is a PACKET device\n");
 
 
    ata_set_device_signature(device, PACKET_SIGNATURE);
    ata_set_device_signature(device, PACKET_SIGNATURE);
    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->size / BYTES_PER_SECTOR) >= 16514064 )
    if ( (tmp = device->size / BYTES_PER_SECTOR) >= 16514064 )
        *buf++ = 16383;
        *buf++ = 16383;
    else
    else
      if ( (tmp /= (HEADS +1) * SECTORS) > 65535 )
      if ( (tmp /= (HEADS +1) * 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++ = HEADS;
    *buf++ = 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++ = SECTORS;
    *buf++ = 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, FIRMWARE, 8);
    strncpy((char *)buf, 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->size / BYTES_PER_SECTOR) > 16514064 )
    if ( (tmp = device->size / BYTES_PER_SECTOR) > 16514064 )
        tmp = 16514064;
        tmp = 16514064;
 
 
    tmp /= (device->internals.heads_per_cylinder +1) * (device->internals.sectors_per_track);
    tmp /= (device->internals.heads_per_cylinder +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->size / BYTES_PER_SECTOR);
    *buf++ = (device->size / BYTES_PER_SECTOR);
    *buf++ = (device->size / BYTES_PER_SECTOR) >> 16;
    *buf++ = (device->size / BYTES_PER_SECTOR) >> 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
    */
    */
    #if   (MWDMA == -1)
    #if   (MWDMA == -1)
      *buf++ = 0x0000;
      *buf++ = 0x0000;
    #elif (MWDMA == 2)
    #elif (MWDMA == 2)
      *buf++ = 0x0007;
      *buf++ = 0x0007;
    #elif (MWDMA == 1)
    #elif (MWDMA == 1)
      *buf++ = 0x0003;
      *buf++ = 0x0003;
    #else
    #else
      *buf++ = 0x0001;
      *buf++ = 0x0001;
    #endif
    #endif
 
 
    /*
    /*
       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++ = 0x0003;
    *buf++ = 0x0003;
 
 
    /*
    /*
       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_NOP_CMD             << 14 |
             SUPPORT_READ_BUFFER_CMD     << 13 |
             SUPPORT_READ_BUFFER_CMD     << 13 |
             SUPPORT_WRITE_BUFFER_CMD    << 12 |
             SUPPORT_WRITE_BUFFER_CMD    << 12 |
             0                           << 11 |   /* obsolete        */
             0                           << 11 |   /* obsolete        */
             SUPPORT_HOST_PROTECTED_AREA << 10 |
             SUPPORT_HOST_PROTECTED_AREA << 10 |
             SUPPORT_DEVICE_RESET_CMD    << 9  |
             SUPPORT_DEVICE_RESET_CMD    << 9  |
             SUPPORT_SERVICE_INTERRUPT   << 8  |
             SUPPORT_SERVICE_INTERRUPT   << 8  |
             SUPPORT_RELEASE_INTERRUPT   << 7  |
             SUPPORT_RELEASE_INTERRUPT   << 7  |
             SUPPORT_LOOKAHEAD           << 6  |
             SUPPORT_LOOKAHEAD           << 6  |
             SUPPORT_WRITE_CACHE         << 5  |
             SUPPORT_WRITE_CACHE         << 5  |
             0                           << 4  |   /* cleared to zero */
             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_SECURITY_MODE       << 1  |
             SUPPORT_SMART               << 0
             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  |
             SUPPORT_SET_MAX             << 8  |
             0                           << 7  |   /* reserved for    */
             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_READ_WRITE_DMA_QUEUED        << 1  |
             SUPPORT_DOWNLOAD_MICROCODE           << 0
             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_NOP_CMD             << 14 |
             SUPPORT_READ_BUFFER_CMD     << 13 |
             SUPPORT_READ_BUFFER_CMD     << 13 |
             SUPPORT_WRITE_BUFFER_CMD    << 12 |
             SUPPORT_WRITE_BUFFER_CMD    << 12 |
             0                           << 11 |   /* obsolete        */
             0                           << 11 |   /* obsolete        */
             SUPPORT_HOST_PROTECTED_AREA << 10 |
             SUPPORT_HOST_PROTECTED_AREA << 10 |
             SUPPORT_DEVICE_RESET_CMD    << 9  |
             SUPPORT_DEVICE_RESET_CMD    << 9  |
             SUPPORT_SERVICE_INTERRUPT   << 8  |
             SUPPORT_SERVICE_INTERRUPT   << 8  |
             SUPPORT_RELEASE_INTERRUPT   << 7  |
             SUPPORT_RELEASE_INTERRUPT   << 7  |
             SUPPORT_LOOKAHEAD           << 6  |
             SUPPORT_LOOKAHEAD           << 6  |
             SUPPORT_WRITE_CACHE         << 5  |
             SUPPORT_WRITE_CACHE         << 5  |
             0                           << 4  |   /* cleared to zero */
             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_SECURITY_MODE       << 1  |
             SUPPORT_SMART               << 0
             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  |
             SUPPORT_SET_MAX             << 8  |
             0                           << 7  |   /* reserved for    */
             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_READ_WRITE_DMA_QUEUED        << 1  |
             SUPPORT_DOWNLOAD_MICROCODE           << 0
             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 |
      *buf++ = 0              << 15 |
               1              << 14 |
               1              << 14 |
               0              << 13 |   /* CBLIBD level (1=Vih, 0=Vil)               */
               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
*/
*/
void ata_initialize_device_parameters_cmd(ata_device *device)
void ata_initialize_device_parameters_cmd(ata_device *device)
{
{
  /* print debug information                                          */
  /* print debug information                                          */
  TRACE("executing command 'initialize device parameters'\n");
  TRACE("executing command 'initialize device parameters'\n");
 
 
  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 = 0;
  device->regs.status = 0;
}
}
 
 
 
 
/*
/*
  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
*/
*/
void ata_read_sectors_cmd(ata_device *device)
void ata_read_sectors_cmd(ata_device *device)
{
{
  size_t sector_count;
  size_t sector_count;
  unsigned long lba;
  unsigned long lba;
 
 
  /* print debug information                                          */
  /* print debug information                                          */
  TRACE("executing command 'read sectors'\n");
  TRACE("executing command 'read sectors'\n");
 
 
  /* check if this is a NON-PACKET device                             */
  /* check if this is a NON-PACKET device                             */
  if (device->packet)
  if (device->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.
    */
    */
    TRACE("'identify_device' command: This is a PACKET device\n");
    TRACE("'identify_device' command: This is a PACKET device\n");
 
 
    ata_set_device_signature(device, PACKET_SIGNATURE);
    ata_set_device_signature(device, PACKET_SIGNATURE);
    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
  {
  {
    /* 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;
 
 
    /* 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 (device->regs.device_head & ATA_DHR_LBA)
    if (device->regs.device_head & ATA_DHR_LBA)
    {   /* we are using LBA translation                               */
    {   /* we are using LBA translation                               */
        lba = (device->regs.device_head & ATA_DHR_H) << 24 |
        lba = (device->regs.device_head & ATA_DHR_H) << 24 |
              (device->regs.cylinder_high          ) << 16 |
              (device->regs.cylinder_high          ) << 16 |
              (device->regs.cylinder_low           ) <<  8 |
              (device->regs.cylinder_low           ) <<  8 |
               device->regs.sector_number
               device->regs.sector_number
        ;
        ;
    }
    }
    else
    else
    {   /* we are using CHS translation, calculate lba address        */
    {   /* we are using CHS translation, calculate lba address        */
        lba  = (device->regs.cylinder_high << 16) | device->regs.cylinder_low;
        lba  = (device->regs.cylinder_high << 16) | device->regs.cylinder_low;
        lba *= device->internals.heads_per_cylinder;
        lba *= device->internals.heads_per_cylinder;
        lba += device->regs.device_head & ATA_DHR_H;
        lba += device->regs.device_head & ATA_DHR_H;
        lba *= device->internals.sectors_per_track;
        lba *= device->internals.sectors_per_track;
        lba += device->regs.sector_number;
        lba += device->regs.sector_number;
        lba -= 1;
        lba -= 1;
    }
    }
 
 
    /* check if sector within bounds                                  */
    /* check if sector within bounds                                  */
    if (lba > (device->size / BYTES_PER_SECTOR) )
    if (lba > (device->size / BYTES_PER_SECTOR) )
    {   /* 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;
    }
    }
    else
    else
    {   /* go ahead, read the bytestream                              */
    {   /* go ahead, read the bytestream                              */
        lba *= BYTES_PER_SECTOR;
        lba *= BYTES_PER_SECTOR;
 
 
        /* set the file-positon pointer to the start of the sector    */
        /* set the file-positon pointer to the start of the sector    */
        fseek(device->stream, lba, SEEK_SET);
        fseek(device->stream, lba, SEEK_SET);
 
 
        /* get the bytes from the stream                              */
        /* get the bytes from the stream                              */
        fread(device->internals.dbuf, BYTES_PER_SECTOR, sector_count, device->stream);
        fread(device->internals.dbuf, BYTES_PER_SECTOR, sector_count, device->stream);
 
 
        /* 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;
 
 
        /* reset the databuffer                                       */
        /* reset the databuffer                                       */
        device->internals.dbuf_cnt = sector_count * BYTES_PER_SECTOR /2; //Words, not bytes
        device->internals.dbuf_cnt = sector_count * BYTES_PER_SECTOR /2; //Words, not bytes
        device->internals.dbuf_ptr = device->internals.dbuf;
        device->internals.dbuf_ptr = device->internals.dbuf;
    }
    }
  }
  }
}
}
 
 
 
 
 
 

powered by: WebSVN 2.1.0

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