Subversion Repositories shark

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

/*
 * Project: S.Ha.R.K.
 *
 * Coordinators:
 *   Giorgio Buttazzo    <giorgio@sssup.it>
 *   Paolo Gai           <pj@gandalf.sssup.it>
 *
 * Authors     :
 *   Paolo Gai           <pj@gandalf.sssup.it>
 *   Massimiliano Giorgi <massy@gandalf.sssup.it>
 *   Luca Abeni          <luca@gandalf.sssup.it>
 *   (see the web pages for full authors list)
 *
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
 *
 * http://www.sssup.it
 * http://retis.sssup.it
 * http://shark.sssup.it
 */



/***************************************

  CVS :        $Id: ide.h,v 1.1.1.1 2002-03-29 14:12:49 pj Exp $
 
  Revision:    $Revision: 1.1.1.1 $

  Last update: $Date: 2002-03-29 14:12:49 $

  Header file for all the modules of the IDE block device interface
  sub-system.

***************************************/


/*
 * Copyright (C) 1999,2000 Massimiliano Giorgi
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */


#ifndef __IDE_H__
#define __IDE_H__

#include "glue.h"
#include "bdev.h"
#include "bqueue.h"

/*+ max number of ide interface (must be <= 8) +*/
#define MAXIDEINTERFACES 4

/*---*/

/*
 * CONSTANTS
 */


/*+ max number of "minor number" required +*/
#define MAXIDEMINOR (MAXIDEINTERFACES<<5)

/*+ max number of "logical partition" per hard disk +*/
#define MAXIDELODSK 16

/*+ number of physical region descriptors used by DMA bus master operations +*/
#define MAXPRDENTRIES 4

/*+ for a master hard disk +*/
#define IDE_MASTER 0x00
/*+ for a slave hard disk +*/
#define IDE_SLAVE  0x01

/*+ sector size in bytes +*/
#define IDE_SECTOR_SIZE 512

/*+ Log Level for errors +*/
#define IDEERRLOG   KERN_ERR
/*+ Log Level for log +*/
#define IDELOG      KERN_NOTICE
/*+ Log Level for debug purpose +*/
#define IDEDEBUGLOG KERN_DEBUG

/*
 * for result
 */


/*+
  This values are returned by the low level routine to indicate
  an error.
  +latex+ \\

  No error +*/

#define IDE_OK                0
/*+ there are too much request pending +*/
#define IDE_ERR_TOOMUCHREQ   -1
/*+ the interface is busy or can not do a command+*/
#define IDE_ERR_BUSY         -2
/*+ the following codes are from the IDE error register +*/
#define IDE_ERR_BADBLOCK     -3
#define IDE_ERR_CRCECC       -4
#define IDE_ERR_IDNOTFOUND   -5
#define IDE_ERR_ABORTCMD     -6
#define IDE_ERR_TRACK00      -7
#define IDE_ERR_DAMNOTFOUND  -8
/*+ generic error (when there are not other IDE_ERR_?? available) +*/
#define IDE_ERR_UNKNOWN      -9
/*+ there was an interrupt, we aspect data but there is not data +*/
#define IDE_ERR_NODATA      -10
/*+ there was an interrupt, we do not aspect data but there is data +*/
#define IDE_ERR_DATA        -11
/*+ interface not ready for a command +*/
#define IDE_ERR_NOTREADY    -12
/*+ a timeout waiting for a reply +*/
#define IDE_ERR_TIMEOUT     -13
/*+ the interface must be busy but it is not +*/
#define IDE_ERR_NOTBUSY     -14
/*+ device fault +*/
#define IDE_ERR_FAULT       -15
/*+ we aspect to send data but there is no data request +*/
#define IDE_ERR_NODATAREQ   -16
/*+ the DRDY signal is not preset +*/
#define IDE_ERR_NOTDRDY     -17
/*+ DMA cycle error +*/
#define IDE_ERR_DMA         -18

/*+ for the IDE_ERR_??? constants +*/
extern char *ide_error_msg[];

/*
 * DATA STRUCTURES
 */


/*+
  Information on IDE devices capabilities
  +*/

struct ide_diskinfo {
  __uint32_t use_lba:1;     /*+ use LBA address translation +*/
  __uint32_t use_dma:1;     /*+ use old dma operation +*/
  __uint32_t use_bm_dma:1;  /*+ use new bus master dma operation +*/
  __int8_t  max_pio_mode;   /*+ max pio mode supported (-1 no support) +*/
  __int8_t  max_dma_mode;   /*+ max multi word dma support (-1 no support) +*/
  __int8_t  max_udma_mode;  /*+ max ultra dma mode support (-1 no support) +*/
};

/*+
  Information on IDE interfaces
  +*/

struct ideinfo {

#ifdef _PARANOIA
  __uint32_t magic;        /*+ magic number +*/
#endif

  __uint16_t io_port;      /*+ I/O address +*/
  __uint16_t io_port2;     /*+ auxiliary I/O address +*/
  __uint8_t  irq;          /*+ irq number +*/
  __uint8_t  dma;          /*+ dma channel +*/
  __uint16_t io_bmdma;     /*+ I/O address for a bus master DMA cycle */

  /* this must be 4-bytes aligned */
  __uint32_t prd[MAXPRDENTRIES*2];
                           /*+ physical region descriptors (used by DMA) */
 
  struct phdskinfo    *pdisk[2]; /*+ physical disk pointer for master/slave +*/
  struct ide_diskinfo info[2];   /*+ more disk information for master/slave +*/

  bqueue_t   queue[2];
  int        actreq;       /*+ actual request that we are serving +*/
  int        actdrv;       /*+ drive id of the actual request +*/
 
  int        errors;       /*+ incremented for every error */
 
  /* for the glue routines (see ideglue.c) */
  __pid_t    server;       /*+ interface server pid +*/

} __attribute__ ((aligned (4)));

/*+
  Information on minor devices
  +*/

struct ideminorinfo {
 
#ifdef _PARANOIA
  __uint32_t  magic;     /*+ magic number +*/  
#endif
 
  __blkcnt_t  start;     /*+ first block of this logical disk (partition) +*/
  __blkcnt_t  size;      /*+ size of the logical disk (in sectors) +*/
 
  __uint16_t  used:1;    /*+ is this entry used? +*/
  __uint16_t  blocked:1; /*+ is this entry blocked? (is someone using it?) +*/
};

/*
 * DATA
 */


/* these are here because are used both ide.c and idelow.c */

extern struct ideinfo ide[MAXIDEINTERFACES];

extern int ide_showinfo_flag;

extern void *ide_parm_initserver;

/*
 * FUNCTIONS
 */


/* register an hardware interface on first free slot */
int ide_register(__uint16_t io_port, __uint16_t io_port2,
                 __uint8_t irq,
                 __uint8_t dma, __uint16_t io_bmdma);
/* release resource used by the ideif interface */
void ide_unregister(int ideif);

/* scan an interface to found device */
int ide_scan(int ideif);

/* scan an hard disk to found a partitions scheme */
int ide_scandisk(int hwif, int drv);


struct ata_diskid;
struct atapi_diskid;

int do_ide_softreset(int ideif);
int ide_read(int ideif, int id, __blkcnt_t lsector, __uint8_t *buffer);
int ide_write(int ideif, int id, __blkcnt_t lsector, __uint8_t *buffer);
int ide_seek(int ideif, int id, __blkcnt_t lsector);
int ide_pidentify(int ideif, int id, struct atapi_diskid *buffer);
int ide_identify(int ideif, int id, struct ata_diskid *buffer);
int ide_enablelookahead(int ideif, int id);
int ide_disablelookahead(int ideif, int id);
int ide_settransfertmode(int ideif, int id, int mode);

TASK ide_server(int ideif);

#define is_ide_free(ideif) (ide[(ideif)].io_port==0)
#define mark_ide_free(ideif) (ide[(ideif)].io_port=0)

static inline int nextideif(void)
{
  int ideif;
  for (ideif=0;ideif<MAXIDEINTERFACES;ideif++)
    if (is_ide_free(ideif)) break;
  return ideif;
}

/*
 * LOW LEVEL data structures
 */


/* ATA-4 */
/* obs: obsolete res: reserved ven: vendor specific */

/*+ IDENTIFY command response (from ATA 4 specifications) +*/
struct ata_diskid {
  __uint16_t  config;
  __uint16_t  def_cyls;
  __uint16_t  res2;
  __uint16_t  def_heads;
  __uint16_t  res4;
  __uint16_t  res5;
  __uint16_t  def_sects;
  __uint16_t  ven7;
  __uint16_t  ven8;
  __uint16_t  ven9;
  __uint8_t   serial[20];
  __uint16_t  ven20;
  __uint16_t  ven21;
  __uint16_t  obs22;
  __uint8_t   firmware[8];
  __uint8_t   model[40];
  __uint16_t  maxmulsect;
  __uint16_t  res48;
  __uint16_t  capabilities;
  __uint16_t  capabilities2;
  __uint8_t   ven51;
  __uint8_t   PIO_mode;
  __uint16_t  ven52;
  __uint16_t  fields_valid;
  __uint16_t  act_cyls;      // 54
  __uint16_t  act_heads;
  __uint16_t  act_sects;
  __uint16_t  cur_capacity0;
  __uint16_t  cur_capacity1; // 58
  __uint8_t   multsect;      
  __uint8_t   multsect_valid;
  __uint32_t  lba_capacity;
  __uint16_t  obs62;
  __uint16_t  DMA_mword;
  __uint8_t   eide_PIO_modes;
  __uint8_t   res64 ;
  __uint16_t  eide_dma_min;
  __uint16_t  eide_dma_time;
  __uint16_t  eide_pio;    
  __uint16_t  eide_pio_iordy;
  __uint16_t  res69;
  __uint16_t  res70;          // 70
  __uint16_t  res71;
  __uint16_t  res72;
  __uint16_t  res73;
  __uint16_t  res74;
  __uint16_t  queue_depth;
  __uint16_t  res76;
  __uint16_t  res77;
  __uint16_t  res78;
  __uint16_t  res79;  
  __uint16_t  major_version;
  __uint16_t  minor_version;
  __uint16_t  command_sets;
  __uint16_t  command_sets2;
  __uint16_t  command_sets_ext;
  __uint16_t  command_sets_ena;
  __uint16_t  command_sets_ena2;
  __uint16_t  command_sets_def;
  __uint16_t  UDMA_cap;
  __uint16_t  erase_time;
  __uint16_t  erase_time2;
  __uint16_t  current_power;
  __uint16_t  reservedA[126-92+1];
  __uint16_t  status_notification;
  __uint16_t  security;
  __uint16_t  vendor[159-129+1];
  __uint16_t  reservedB[255-160+1];
} __attribute__((packed));

#define is_ATAdevice(p)    ((p)->config&0x8000)
#define is_removable(p)    ((p)->config&0x0080)
#define is_notremovable(p) ((p)->config&0x0040)

// 54 -> 58
#define is_actcurvalid(p)  ((p)->fields_valid&0x0001)
// 64 -> 70
#define is_eidevalid(p)    ((p)->fields_valid&0x0002)
// 88
#define is_udmavalid(p)  ((p)->fields_valid&0x0004)

#define is_ATA(p)          ((p)->major_version&0x02)
#define is_ATA2(p)         ((p)->major_version&0x04)
#define is_ATA3(p)         ((p)->major_version&0x08)
#define is_ATA4(p)         ((p)->major_version&0x10)

#define is_LBAcapable(p)   ( \
                            ((p)->capabilities&0x0200) \
                            || is_ATA3(p) \
                            || is_ATA4(p) \
                           )


/*+ PIDENTIFY command response (for ATAPI device from ATA 4 specs) +*/
struct atapi_diskid {
  __uint16_t  config;
  __uint16_t  res1;
  __uint16_t  res2;
  __uint16_t  res3;
  __uint16_t  res4;
  __uint16_t  res5;
  __uint16_t  res6;
  __uint16_t  ven7;
  __uint16_t  ven8;
  __uint16_t  ven9;
  __uint8_t   serial[20];
  __uint16_t  res20;
  __uint16_t  res21;
  __uint16_t  res22;
  __uint8_t   firmware[8];
  __uint8_t   model[40];
  __uint16_t  res47;
  __uint16_t  res48;
  __uint16_t  capabilities;
  __uint16_t  res50;
  __uint8_t   ven51;
  __uint8_t   tPIO;
  __uint16_t  res52;
  __uint16_t  fields_valid;
  __uint16_t  res54;   //54
  __uint16_t  res55;
  __uint16_t  res56;
  __uint16_t  res57;
  __uint16_t  res58;  // 58
  __uint16_t  res59;
  __uint16_t  res60;
  __uint16_t  res61;
  __uint16_t  res62;
  __uint16_t  dma_mword;
  __uint16_t  eide_pio_modes; //64
  __uint16_t  eide_dma_min;
  __uint16_t  eide_dma_time;
  __uint16_t  eide_pio;    
  __uint16_t  eide_pio_iordy;
  __uint16_t  res69;
  __uint16_t  res70;          // 70
  __uint16_t  time_packet;
  __uint16_t  time_service;
  __uint16_t  res73;
  __uint16_t  res74;
  __uint16_t  queue_depth;
  __uint16_t  res76;
  __uint16_t  res77;
  __uint16_t  res78;
  __uint16_t  res79;  
  __uint16_t  major_version;
  __uint16_t  minor_version;
  __uint16_t  command_sets;
  __uint16_t  command_sets2;
  __uint16_t  command_sets_ext;
  __uint16_t  command_sets_ena;
  __uint16_t  command_sets_ena2;
  __uint16_t  command_sets_def;
  __uint16_t  udma;
  __uint16_t  reservedA[126-89+1];
  __uint16_t  status_notification;
  __uint16_t  security;
  __uint16_t  vendor[159-129+1];
  __uint16_t  reservedB[255-160+1];
} __attribute__((packed));

#define is_ATAPIdevice(p)  (((p)->config&0xc000)==0x8000)
//#define is_removable(p)    ((p)->config&0x0080)
#define is_packet12capable(p) (((p)->conig&0x0003)==0x0000)
#define is_packet16capable(p) (((p)->conig&0x0003)==0x0001)

#define is_directdev(p)        ((((p)->config&0x1f00)>>8)==0x00)
#define is_sequentialdev(p)    ((((p)->config&0x1f00)>>8)==0x01)
#define is_printerdev(p)       ((((p)->config&0x1f00)>>8)==0x02)
#define is_processordev(p)     ((((p)->config&0x1f00)>>8)==0x03)
#define is_writeoncedev(p)     ((((p)->config&0x1f00)>>8)==0x04)
#define is_cdromdev(p)         ((((p)->config&0x1f00)>>8)==0x05)
#define is_scannerdev(p)       ((((p)->config&0x1f00)>>8)==0x06)
#define is_opticalmemorydev(p) ((((p)->config&0x1f00)>>8)==0x07)
#define is_mediachengerdev(p)  ((((p)->config&0x1f00)>>8)==0x08)
#define is_communicatordev(p)  ((((p)->config&0x1f00)>>8)==0x09)
#define is_arraydev(p)         ((((p)->config&0x1f00)>>8)==0x0c)

#endif