/***************************************************
 *  Header file for eata.c Linux EATA SCSI driver  *
 *  currently contains lots of unused stuff        *
 *  (c) 1993,94 Michael Neuffer                    *
 ***************************************************
 * last change: 20.09.94                           *
 ***************************************************/


#ifndef _EATA_H
#define _EATA_H

#include "../block/blk.h"
#include "scsi.h"
#include "hosts.h"


#define VER_MAJOR 0
#define VER_MINOR 3
#define VER_SUB   "a"

/************************************************************************
 * Here you can configure your drives that are running in IDE           *
 * emulation mode                                                       *
 * If all your drives are running in native mode (not emulated), set    *
 * IDE_EMULATION to 0                                                   * 
 * If you have only one drive (running in IDE emu. mode), set ID1 to -1 *
 ************************************************************************/
#define IDE_EMULATION 1          /* Here are drives running in emu. mode   */

#define ID0           0          /* SCSI ID of "IDE" drive mapped to C:    */
                                 /* If you're not sure check your config
				  * utility that came with your controller
				  */
#define HEADS0       13          /* Number of emulated heads of this drive */  
#define SECTORS0     38          /* Number of emulated sectors             */ 
#define CYLINDER0   719          /* Number of emulated cylinders           */
   
#define ID1           1          /* SCSI ID of "IDE" drive mapped to D:    */
#define HEADS1       16          /* Number of emulated heads of this drive */ 
#define SECTORS1     62          /* Number of emulated sectors             */
#define CYLINDER1  1024          /* Number of emulated cylinders           */

/************************************************************************
 * Debug options.                                                       * 
 * Enable DEBUG and whichever options you require.                      *
 ************************************************************************/
#define DEBUG		0	/* Enable debug code. 			*/
#define DBG_PROBE	1	/* Debug probe routines. 		*/
#define	DBG_DUMP	1	/* Dump response to probes in hex. 	*/
#define DBG_DELAY	0	/* Build in delays so debug messages can be
				 * be read before they vanish of the top of
				 * the screen!
				 */
#define DBG_FUNC	1	/* Trace function calls. 		*/
#define DBG_TRAP	1	/* Trap errors from higher levels.	*/
#define DBG_QUEUE	1	/* Trace command queueing. 		*/
#define DBG_INTR	0       /* Trace interrupt service routine. 	*/
#define DBG_WINTR       1       /* Trace Wait for interrupt             */
#define DBG_ABNORM	1	/* Debug abnormal actions (reset, abort)*/
#define DBG_AHMON       0       /* Ahmon's special  (-;                 */  

#if DEBUG
static char dummy;
#define DBG(x, y)	if ((x)) {y;} else dummy=0
#else
#define DBG(x, y)
#endif

#if DEBUG && DBG_DELAY
#define DELAY(x)	if (1) { int i; i = jiffies + x; while (jiffies < i); } else dummy=0
#else
#define DELAY(x)	
#endif


#define EATA {                       \
	NULL,                        \
        "Generic EATA - DMA (rev. 2.0b) driver", \
        eata_detect,                 \
        NULL,                        \
        eata_info,                   \
        eata_command,                \
        eata_queue,                  \
        eata_abort,                  \
        eata_reset,                  \
        NULL, /* Slave attach */     \
        eata_biosparam,              \
        1,      /* Canqueue */       \
        7,      /* this_id */        \
        64,     /* sg_tablesize */   \
        1,      /* cmd_per_lun */    \
        0,      /* present */        \
        0,      /* unchecked_isa_dma */\
	ENABLE_CLUSTERING }

int eata_detect(Scsi_Host_Template *);
const char *eata_info(void);
int eata_command(Scsi_Cmnd *);
int eata_queue(Scsi_Cmnd *, void *(done)(struct scsi_cmnd *));
int eata_abort(Scsi_Cmnd *);
int eata_reset(Scsi_Cmnd *);
int eata_biosparam(Disk *, int, int []);


typedef unsigned char byte;

/***********************************************
 *         EATA Register definitions           *
 ***********************************************/

#define EATA_CMD_PIO_READ_CONFIG 0xf0
#define EATA_CMD_PIO_SET_CONFIG  0xf1
#define EATA_CMD_PIO_SEND_CP     0xf2
#define EATA_CMD_PIO_RECEIVE_SP  0xf3
#define EATA_CMD_PIO_TRUNC       0xf4
#define EATA_CMD_RESET           0xf9

#define EATA_CMD_DMA_READ_CONFIG 0xfd
#define EATA_CMD_DMA_SET_CONFIG  0xfe
#define EATA_CMD_DMA_SEND_CP     0xff

#define ECS_EMULATE_SENSE        0xd4

#define HA_WCOMMAND 0x07        /* command register offset   */
#define HA_WDMAADDR 0x02        /* DMA address LSB offset    */  
#define HA_RAUXSTAT 0x08        /* aux status register offset*/
#define HA_RSTATUS  0x07        /* status register offset    */
#define HA_RDATA    0x00        /* data register (16bit)     */

#define HA_ABUSY    0x01        /* aux busy bit              */
#define HA_AIRQ     0x02        /* aux IRQ pending bit       */
#define HA_SERROR   0x01        /* pr. command ended in error*/
#define HA_SMORE    0x02        /* more data soon to come    */
#define HA_SCORR    0x04        /* data corrected            */
#define HA_SDRQ     0x08        /* data request active       */
#define HA_SSC      0x10        /* seek complete             */
#define HA_SFAULT   0x20        /* write fault               */
#define HA_SRDY     0x40        /* drive ready               */
#define HA_SBSY     0x80        /* drive busy                */
#define HA_SDRDY    HA_SSC+HA_SRDY+HA_SDRQ 

struct reg_bit {        /* reading this one will clear the interrupt 	*/
  byte error:1;     /* previous command ended in an error           */
  byte more:1;      /* more DATA comming soon, poll BSY & DRQ (PIO) */
  byte corr:1;      /* data read was successfully corrected with ECC*/
  byte drq:1;       /* data request aktive  */     
  byte sc:1;        /* seek complete        */
  byte fault:1;     /* write fault          */
  byte ready:1;     /* drive ready          */
  byte busy:1;      /* controller busy      */
};

struct reg_abit {       /* reading this won't clear the interrupt */
  byte abusy:1;     /* auxiliary busy                         */
  byte irq:1;       /* set when drive interrupt is asserted   */
  byte dummy:6;
};

struct eata_register {      	    /* EATA register set */
  byte data_reg[2];     	/* R, couldn't figure this one out          */
  byte cp_addr[4];      	/* W, CP address register                   */
  union { 
    byte command;     	        /* W, command code: [read|set] conf, send CP*/
    struct reg_bit status;	/* R, see register_bit1                     */
    byte statusbyte;
  } ovr;   
  struct reg_abit aux_stat; 	/* R, see register_bit2               	    */
};

/**********************************************
 *  Other (command) definitions               *
 **********************************************/

struct gco_bits1 {
  byte OCS_enabled:1;	        /* Overlap Command Support enabled  	*/
  byte TAR_support:1;	        /* SCSI Target Mode supported		*/
  byte TRNXFR:1;		/* Truncate Transfer Cmd not necessary	*/
                                /* Only used in PIO Mode 		*/
  byte MORE_support:1;	        /* MORE supported (only PIO Mode) 	*/
  byte DMA_support:1;	        /* DMA supported Driver uses only 	*/
                        	/* this mode				*/
  byte DRQ_valid:1;		/* DRQ value in Byte 30 is valid	*/
  byte ATA:1;		        /* ATA device connected (no support)	*/
  byte HAA_valid:1;		/* Hostadapter Address is valid     	*/
};

struct gco_bits2 {
  byte IRQ:4;                 /* IRQ used this HA			*/
  byte SECOND:1;              /* This is a secondary controller	        */
  byte IRQ_TR:1;              /* IRQ Trigger: 0=edge, 1=level	        */
  byte DRQX:2;                /* DRQ index, DRQ is 2comp of DRQX	*/
};

struct get_conf {               /* Read Configuration Array  */
  byte gco_len[4];            /* Should return 0x1c 			*/
  byte gco_sig[4];            /* Signature MUST be "EATA" 		*/
  byte gco_version;           /* upper nibble contains Version      	*/
  struct gco_bits1 bit1;				
  byte gco_cppadlen[2];	      /* Number of pad bytes send after CD data */
                              /* set to zero for DMA commands		*/
  byte gco_HAaddress[4];      /* SCSI ID of controller if SCSI device   */
                              /* if not, zero is returned 		*/
  byte gco_cplen[4];	      /* CP length: number of valid cp bytes 	*/
  byte gco_splen[4];	      /* Number of bytes returned after	        */ 
                              /* Receive SP command			*/
  byte gco_queuesiz[2];	      /* max number of queueable CPs		*/
  byte gco_dummy[2];
  byte gco_SGsiz[2];	      /* max number of SG table entries	        */
  struct gco_bits2 bit2;
  byte gco_sync;              /* device at ID 7 tru 0 is running in 	*/
                              /* synchronous mode                       */
  byte gco_unused[480];
};

struct sco_bits {
  byte EATA_disable:1;	      /* Disable EATA interface :-(		*/
  byte OC_enable:1;	      /* Enable overlapped commands		*/
  byte MPD_enable:1;	      /* Enable sending of all Save, Restore    */
                              /* and Modify Data Pointer Messages       */
  byte TAR_enable:1;          /* Enable HA Target mode	       	        */
}; 

struct set_conf {	      /* Set Configuration Array */
  byte sco_trlen[2];          /* Number of bytes following this field	*/
  struct sco_bits bit;
  byte sco_zero;              /* set this one to zero       		*/  
  char   sco_unused[508];
};

#define HA_DATA_IN  0x80
#define HA_DATA_OUT 0x40
#define HA_SC_GA    0x08


struct cp_bits {              /* Send Command Packet Bits           */
  byte SCSI_Reset:1;          /* Cause a SCSI Bus reset on the cmd  */
  byte HBA_Init:1;            /* Cause Controller to reInitialize   */
  byte Auto_Req_Sen:1;        /* Do Auto Request Sense on errors    */
  byte scatter:1;             /* Data Ptr points to a SG Packet     */
  byte Resrvd:1;              /* RFU                                */
  byte Interpret:1;           /* Interpret the SCSI cdb of own use  */
  byte DataOut:1;             /* Data Out phase with command        */
  byte DataIn:1;              /* Data In phase with command         */
};

struct cp_bits2 {
  byte Phsunit:1;             /* physical unit on mirrored pair	    */
  byte Iat:1;                 /* inhibit address translation        */
  byte HBA_Cin:1;             /* HBA Inhibit caching                */
};

struct eata_ccb {             /* Send Command Packet structure      */
  union {
    struct cp_bits bit;       /* CP Bits			    */
    byte Byte;
  } cp_option;
  byte reqlen;     	      /* Request Sense Length               */ 
                              /* Valid if Auto_Req_Sen=1            */
  byte unused[4];
  union {
    struct cp_bits2 bit;      /* Send command direct to physical unit   */   
    byte Byte;
  } cp_option2;
  byte cp_id;                 /* SCSI Device ID of target       */ 
  byte cp_msg0;               /* Message bytes 0-3              */
  byte cp_msg1;
  byte cp_msg2;
  byte cp_msg3;
  byte cp_cdb[12];    	      /* Command Descriptor Block       */
  byte cp_datalen[4]; 	      /* Data Transfer Length           */
                              /* If scatter=1 len of sg package */
  byte cp_viraddr[4];         /* Virtual address of CP          */
  byte cp_dataDMA[4]; 	      /* Data Address, if scatter=1     */
                              /* address of scatter packet      */  
  byte cp_statDMA[4];         /* address for Status Packet      */ 
  byte cp_reqDMA[4];          /* Request Sense Address, used if */
                              /* CP command ends with error     */
};


struct eata_sp
{
  byte cont_stat, scsi_stat, reserved[2];
  byte residue_len[4], cp_id[4], msg[12];
};

struct eata_cmd_queue
{
  int used;
  struct eata_sp  sp;
  struct eata_ccb cp;
  Scsi_Cmnd *cmd;
};

struct eata_sg_list
{
        void *data;
        int len;
};




/* structure for max. 2 emulated drives */
struct drive_geom_emul {
  byte trans;                 /* translation flag 1=transl */
  int  channel;               /* SCSI channel number       */
  byte HBA;                   /* HBA number (prim/sec)     */
  byte id;                    /* drive id                  */
  byte lun;                   /* drive lun                 */
  uint heads;                 /* number of heads           */
  uint sectors;               /* number of sectors         */
  uint cylinder;              /* number of cylinders       */
};

struct geom_emul {
  int bios_drives;               /* number of emulated drives */
  struct drive_geom_emul drv[2]; /* drive structures          */
};

struct emul_sense {
  byte Byte0;
  byte Cyls[2];
  byte Heads;
  byte Sectors;
  byte padding;
  byte drtype[2];
  byte lunmap[8];
};

/**********************************************
 * Message definitions                        *
 **********************************************/
#define HA_IDENTIFY_MSG 0x80       /* Sent identify message      */
#define HA_G_DISCO_RECO 0x40       /* Grant disconnect privilege */

/*********************************************
 * Misc. definitions                         *
 *********************************************/
#define EXP_NOTHING 0
#define EXP_RETURN  2
#define EXP_NORMAL  1


#define xscsi2int(up) ( (((long)(up)[0]) << 24) + (((long)(up)[1]) << 16) \
                      + (((long)(up)[2]) <<  8) +  ((long)(up)[3]) )

#endif /* _EATA_H */
