/****************************************************************/
/*                                                              */
/*                           device.h                           */
/*                      Device Driver Header File               */
/*                                                              */
/*                       November 20, 1991                      */
/*                                                              */
/*                      Copyright (c) 1995                      */
/*                      Pasquale J. Villani                     */
/*                      All Rights Reserved                     */
/*                                                              */
/* This file is part of DOS-C.                                  */
/*                                                              */
/* DOS-C 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, or (at your option) any later version.                    */
/*                                                              */
/* DOS-C 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 DOS-C; see the file COPYING.  If not,     */
/* write to the Free Software Foundation, 675 Mass Ave,         */
/* Cambridge, MA 02139, USA.                                    */
/****************************************************************/

#ifdef MAIN
#ifdef VERSION_STRINGS
static BYTE *device_hRcsId =
    "$Id$";
#endif
#endif

/*
 *      Status Word Bits
 */

#define S_ERROR         0x8000  /* Error bit                    */
#define S_BUSY          0x0200  /* Device busy bit              */
#define S_DONE          0x0100  /* Device operation completed   */
#define S_MASK          0x00ff  /* Mask to extract error code   */

/*
 *      MEDIA Descriptor Byte Bits
 */

#define MD_2SIDE        1       /* MEDIA is two sided           */
#define MD_8SECTOR      2       /* MEDIA is eight sectored      */
#define MD_REMOVABLE    4       /* MEDIA is removable (floppy)  */

/*
 *      Media Return Codes
 */
#define M_CHANGED       -1      /* MEDIA was changed            */
#define M_DONT_KNOW     0       /* MEDIA state unkown           */
#define M_NOT_CHANGED   1       /* MEDIA was not changed        */

/*
 *      Error Return Codes
 */

#define E_WRPRT         0       /* Write Protect                */
#define E_UNIT          1       /* Unknown Unit                 */
#define E_NOTRDY        2       /* Device Not Ready             */
#define E_CMD           3       /* Unknown Command              */
#define E_CRC           4       /* Crc Error                    */
#define E_LENGTH        5       /* Bad Length                   */
#define E_SEEK          6       /* Seek Error                   */
#define E_MEDIA         7       /* Unknown MEDIA                */
#define E_NOTFND        8       /* Sector Not Found             */
#define E_PAPER         9       /* No Paper                     */
#define E_WRITE         10      /* Write Fault                  */
#define E_READ          11      /* Read Fault                   */
#define E_FAILURE       12      /* General Failure              */

/*
 *      Command codes
 */

#define C_INIT          0x00    /* Initialize                   */
#define C_MEDIACHK      0x01    /* MEDIA Check                  */
#define C_BLDBPB        0x02    /* Build BPB                    */
#define C_IOCTLIN       0x03    /* Ioctl In                     */
#define C_INPUT         0x04    /* Input (Read)                 */
#define C_NDREAD        0x05    /* Non-destructive Read         */
#define C_ISTAT         0x06    /* Input Status                 */
#define C_IFLUSH        0x07    /* Input Flush                  */
#define C_OUTPUT        0x08    /* Output (Write)               */
#define C_OUTVFY        0x09    /* Output with verify           */
#define C_OSTAT         0x0a    /* Output                       */
#define C_OFLUSH        0x0b    /* Output Flush                 */
#define C_IOCTLOUT      0x0c    /* Ioctl Out                    */
#define C_OPEN          0x0d    /* Device Open                  */
#define C_CLOSE         0x0e    /* Device Close                 */
#define C_REMMEDIA      0x0f    /* Removable MEDIA              */
#define C_OUB           0x10    /* Output till busy             */
#define C_GENIOCTL      0x13    /* Generic Ioctl                */
#define C_GETLDEV       0x17    /* Get Logical Device           */
#define C_SETLDEV       0x18    /* Set Logical Device           */
#define C_IOCTLQRY      0x19    /* Ioctl Query                  */

/*
 *      Convienence macros
 */
#define failure(x)      (S_ERROR+S_DONE+x)
#ifndef TRUE
#define TRUE            1
#endif
#ifndef FALSE
#define FALSE           0
#endif
#define mk_offset(far_ptr)      ((UWORD)(far_ptr))
#define mk_segment(far_ptr) ((UWORD)((ULONG)(far_ptr) >> 16))
#define far_ptr(seg, off) ((VOID FAR *)(((ULONG)(off))+((ULONG)(seg) << 16)))

/*
 *      structures
 */

/* Device header */

struct dhdr {
  struct dhdr
  FAR *dh_next;
  UWORD dh_attr;
    VOID(*dh_strategy) (void);
    VOID(*dh_interrupt) (void);
  BYTE dh_name[8];
};

#define ATTR_SUBST      0x8000
#define ATTR_CHAR       0x8000
#define ATTR_IOCTL      0x4000
#define ATTR_BLDFAT     0x2000
#define ATTR_REMOTE     0x1000
#define ATTR_EXCALLS    0x0800
#define ATTR_QRYIOCTL   0x0080
#define ATTR_GENIOCTL   0x0040
#define ATTR_RAW        0x0400
#define ATTR_FASTCON    0x0010
#define ATTR_CLOCK      0x0008
#define ATTR_NULL       0x0004
#define ATTR_CONOUT     0x0002
#define ATTR_HUGE       0x0002
#define ATTR_CONIN      0x0001

/*                                                                      */
/* Bios Parameter Block structure                                       */
/*                                                                      */

#define FAT_NO_MIRRORING 0x80

#define BPB_SIZEOF 31           /* size of the standard BPB */

typedef struct {
  UWORD bpb_nbyte;              /* Bytes per Sector             */
  UBYTE bpb_nsector;            /* Sectors per Allocation Unit  */
  UWORD bpb_nreserved;          /* # Reserved Sectors           */
  UBYTE bpb_nfat;               /* # FAT's                      */
  UWORD bpb_ndirent;            /* # Root Directory entries     */
  UWORD bpb_nsize;              /* Size in sectors              */
  UBYTE bpb_mdesc;              /* MEDIA Descriptor Byte        */
  UWORD bpb_nfsect;             /* FAT size in sectors          */
  UWORD bpb_nsecs;              /* Sectors per track            */
  UWORD bpb_nheads;             /* Number of heads              */
  ULONG bpb_hidden;             /* Hidden sectors               */
  ULONG bpb_huge;               /* Size in sectors if           */
  /* bpb_nsize == 0               */
#ifdef WITHFAT32
  ULONG bpb_xnfsect;            /* FAT size in sectors if       */
  /* bpb_nfsect == 0              */
  UWORD bpb_xflags;             /* extended flags               */
  /* bit 7: disable mirroring     */
  /* bits 6-4: reserved (0)       */
  /* bits 3-0: active FAT number  */
  UWORD bpb_xfsversion;         /* filesystem version           */
  ULONG bpb_xrootclst;          /* starting cluster of root dir */
  UWORD bpb_xfsinfosec;         /* FS info sector number,       */
  /* 0xFFFF if unknown            */
  UWORD bpb_xbackupsec;         /* backup boot sector number    */
  /* 0xFFFF if unknown            */
#endif
} bpb;

#define N_RETRY         5       /* number of retries permitted  */
#define SEC_SIZE        512     /* size of sector in bytes      */

#define LBA_READ         0x4200
#define LBA_WRITE        0x4300

struct _bios_LBA_address_packet
                                           /* Used to access a hard disk via LBA */
 /*       Added by Brian E. Reifsnyder */
{
  unsigned char packet_size;    /* size of this packet...set to 16  */
  unsigned char reserved_1;     /* set to 0...unused                */
  unsigned char number_of_blocks;       /* 0 < number_of_blocks < 128       */
  unsigned char reserved_2;     /* set to 0...unused                */
  UBYTE far *buffer_address;    /* addr of transfer buffer          */
  unsigned long block_address;  /* LBA address                      */
  unsigned long block_address_high;     /* high bytes of LBA addr...unused  */
};

struct CHS {
  UWORD Cylinder;
  UWORD Head;
  UWORD Sector;
};

/* DOS 4.0-7.0 drive data table (see RBIL at INT2F,AX=0803) */
typedef struct ddtstruct {
  struct ddtstruct FAR *ddt_next;
  /* pointer to next table (offset FFFFh if last table) */
  UBYTE ddt_driveno;            /* physical unit number (for INT 13)     */
  UBYTE ddt_logdriveno;         /* logical drive number (0=A:)        */
  bpb ddt_bpb;                  /* BIOS Parameter Block */
  UBYTE ddt_flags;
  /* bit 6: 16-bit FAT instead of 12-bit
     bit 7: unsupportable disk (all accesses will return Not Ready) */
  UWORD ddt_FileOC;             /* Count of Open files on Drv */
  UBYTE ddt_type;               /* device type       */
  UWORD ddt_descflags;          /* bit flags describing drive */
  UWORD ddt_ncyl;               /* number of cylinders
                                   (for partition only, if hard disk) */
  bpb ddt_defbpb;               /* BPB for default (highest) capacity supported */
  UBYTE ddt_reserved[6];        /* (part of BPB above) */
  UBYTE ddt_ltrack;             /* last track accessed */
  union {
    ULONG ddt_lasttime;         /* removable media: time of last access
                                   in clock ticks (FFFFFFFFh if never) */
    struct {
      UWORD ddt_part;           /* partition (FFFFh = primary, 0001h = extended)
                                   always 0001h for DOS 5+ */
      UWORD ddt_abscyl;         /* absolute cylinder number of partition's
                                   start on physical drive
                                   (FFFFh if primary partition in DOS 4.x) */
    } ddt_hd;
  } ddt_fh;
  UBYTE ddt_volume[12];         /* ASCIIZ volume label or "NO NAME    " if none
                                   (apparently taken from extended boot record
                                   rather than root directory) */
  ULONG ddt_serialno;           /* serial number */
  UBYTE ddt_fstype[9];          /* ASCIIZ filesystem type ("FAT12   " or "FAT16   ") */
  ULONG ddt_offset;             /* relative partition offset */
  BITS ddt_LBASupported:1;      /* set, if INT13 extensions enabled */
  BITS ddt_WriteVerifySupported:1;
} ddt;

/* description flag bits */
#define DF_FIXED      0x001
#define DF_CHANGELINE 0x002
#define DF_CURBPBLOCK 0x004
#define DF_SAMESIZE   0x008
#define DF_MULTLOG    0x010
#define DF_CURLOG     0x020
#define DF_DISKCHANGE 0x040
#define DF_DPCHANGED  0x080
#define DF_REFORMAT   0x100
#define DF_NOACCESS   0x200

/* typedef struct ddtstruct ddt;*/

struct gblkio {
  UBYTE gbio_spcfunbit;
  UBYTE gbio_devtype;
  UWORD gbio_devattrib;
  UWORD gbio_ncyl;
  UBYTE gbio_media;
  bpb gbio_bpb;
  UWORD gbio_nsecs;
};

struct gblkfv                   /* for format / verify track */
{
  UBYTE gbfv_spcfunbit;
  UWORD gbfv_head;
  UWORD gbfv_cyl;
  UWORD gbfv_ntracks;
};

struct gblkrw                   /* for read / write track */
{
  UBYTE gbrw_spcfunbit;
  UWORD gbrw_head;
  UWORD gbrw_cyl;
  UWORD gbrw_sector;
  UWORD gbrw_nsecs;
  UBYTE FAR *gbrw_buffer;
};

struct Gioc_media {
  WORD ioc_level;
  ULONG ioc_serialno;
  BYTE ioc_volume[11];
  BYTE ioc_fstype[8];
};

/*                                                                      */
/* Boot Block (Super Block)                                             */
/*                                                                      */
/* See BPB comments for the offsets below                               */
/*                                                                      */
#define BT_JUMP         0
#define BT_OEM          3
#define BT_BPB          11
#define BT_SIZEOF       36

typedef struct {
  BYTE bt_jump[3];              /* Boot Jump opcodes            */
  BYTE bt_oem[8];               /* OEM Name                     */
  bpb bt_bpb;                   /* BPB for this media/device    */
  WORD bt_nsecs;                /* # Sectors per Track          */
  WORD bt_nheads;               /* # Heads                      */
  WORD bt_hidden;               /* # Hidden sectors             */
  LONG bt_huge;                 /* use if nsecs == 0            */
  BYTE bt_drvno;
  BYTE bt_reserv;
  BYTE bt_btid;
  ULONG bt_serialno;
  BYTE bt_volume[11];
  BYTE bt_fstype[8];
} boot;

/* File system information structure */
struct fsinfo {
  UDWORD fi_signature;          /* must be 0x61417272 */
  DWORD fi_nfreeclst;           /* number of free clusters, -1 if unknown */
  DWORD fi_cluster;             /* most recently allocated cluster, -1 if unknown */
  UBYTE fi_reserved[12];
};

typedef boot super;             /* Alias for boot structure             */

typedef struct {
  UBYTE r_length;               /*  Request Header length               */
  UBYTE r_unit;                 /*  Unit Code                           */
  UBYTE r_command;              /*  Command Code                        */
  WORD r_status;                /*  Status                              */
  BYTE r_reserved[8];           /*  DOS Reserved Area                   */
  union {
    struct {
      UBYTE _r_nunits;          /*  number of units     */
      BYTE FAR *_r_endaddr;     /*  Ending Address      */
      bpb *FAR * _r_bpbptr;     /*  ptr to BPB array    */
      UBYTE _r_firstunit;
    } _r_init;
    struct {
      BYTE _r_meddesc;          /*  MEDIA Descriptor    */
      BYTE _r_retcode;          /*  Return Code         */
      BYTE FAR * _r_vid;        /* volume id */
    } _r_media;
    struct {
      BYTE _r_meddesc;          /*  MEDIA Descriptor    */
      boot FAR * _r_fat;        /*  boot sector pointer */
      bpb FAR * _r_bpbpt;       /*  ptr to BPB table    */
    } _r_bpb;
    struct {
      BYTE _r_meddesc;          /*  MEDIA Descriptor    */
      BYTE FAR * _r_trans;      /*  Transfer Address    */
      UWORD _r_count;           /*  Byte/Sector Count   */
      UWORD _r_start;           /*  Starting Sector No. */
      BYTE FAR * _r_vid;        /* Pointer to volume id */
      LONG _r_huge;             /* for > 32Mb drives    */
    } _r_rw;
    struct {
      unsigned char _r_ndbyte;  /*  Byte Read From Device       */
    } _r_nd;
  } _r_x;
} request;

#define HUGECOUNT       0xffff
#define MAXSHORT        0xffffl

/*
 * Macros to assist request structure legibility
 */

/* Init packet macros                                                   */
#define r_nunits        _r_x._r_init._r_nunits
#define r_endaddr       _r_x._r_init._r_endaddr
#define r_bpbptr        _r_x._r_init._r_bpbptr
#define r_firstunit     _r_x._r_init._r_firstunit

/* MEDIA Check packet macros                                            */
#define r_mcmdesc       _r_x._r_media._r_meddesc
#define r_mcretcode     _r_x._r_media._r_retcode
#define r_mcvid         _r_x._r_media._r_vid

/* Build BPB packet macros                                              */
#define r_bpmdesc       _r_x._r_bpb._r_meddesc
#define r_bpfat         _r_x._r_bpb._r_fat
#define r_bpptr         _r_x._r_bpb._r_bpbpt

/* rw packet macros                                                     */
#define r_meddesc       _r_x._r_rw._r_meddesc
#define r_trans         _r_x._r_rw._r_trans
#define r_count         _r_x._r_rw._r_count
#define r_start         _r_x._r_rw._r_start
#define r_rwvid         _r_x._r_rw._r_vid
#define r_huge          _r_x._r_rw._r_huge

/* ndread packet macros                                                 */
#define r_ndbyte        _r_x._r_nd._r_ndbyte

/*
 *interrupt support (spl & splx) support - IBM style
 */

#define I_NONE          0       /* Initial value                */

/* predefined interrupt levels - 8259 support                           */
#define IRQ0            0x01    /* Level 0 - highest            */
#define IRQ1            0x02
#define IRQ2            0x04
#define IRQ3            0x08
#define IRQ4            0x10
#define IRQ5            0x20
#define IRQ6            0x40
#define IRQ7            0x80    /* Level 7 - lowest             */

/* standard hardware configuration                                      */
#define I_RTC           IRQ0    /* Timer                        */
#define I_KBD           IRQ1    /* Keyboard                     */
#define I_COM2          IRQ3    /* COM1:                        */
#define I_COM1          IRQ4    /* COM2:                        */
#define I_HDC           IRQ5    /* Fixed disk                   */
#define I_FDC           IRQ6    /* Diskette                     */
#define I_PRT           IRQ7    /* Printer                      */

/* standard hardware vectors - 8259 defined                             */
#define V_RTC           0x08    /* Timer                        */
#define V_KBD           0x09    /* Keyboard                     */
#define V_LEV2          0x0a    /* Level 2 - uncomitted         */
#define V_COM2          0x0b    /* COM1:                        */
#define V_COM1          0x0c    /* COM2:                        */
#define V_HDC           0x0d    /* Fixed disk                   */
#define V_FDC           0x0e    /* Diskette                     */
#define V_PRT           0x0f    /* Printer                      */

#define V_LEV0          0x08    /* Level 0 - highest            */
#define V_LEV1          0x09
#define V_LEV2          0x0a    /* Level 2 - uncomitted         */
#define V_LEV3          0x0b
#define V_LEV4          0x0c
#define V_LEV5          0x0d
#define V_LEV6          0x0e
#define V_LEV7          0x0f    /* Level 7 - lowest             */

/*
 */
typedef request FAR *rqptr;
typedef bpb FAR *bpbptr;
typedef BYTE FAR *byteptr;
typedef struct dhdr FAR *dhdrptr;

extern request                  /* I/O Request packets                  */
  ASM CharReqHdr, ASM IoReqHdr, ASM MediaReqHdr;

/* dsk.c */
COUNT ASMCFUNC FAR blk_driver(rqptr rp);
ddt * getddt(int dev);

/* error.c */
COUNT char_error(request * rq, struct dhdr FAR * lpDevice);
COUNT block_error(request * rq, COUNT nDrive, struct dhdr FAR * lpDevice);
/* sysclk.c */
WORD ASMCFUNC FAR clk_driver(rqptr rp);

/* execrh.asm */
WORD ASMCFUNC execrh(request FAR *, struct dhdr FAR *);

/*
 *      end of device.h
 */