mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
618 lines
23 KiB
618 lines
23 KiB
/*
|
|
* SoftPC Version 2.0
|
|
*
|
|
* Title : Generic Floppy Interface level definitions
|
|
*
|
|
* Description : Data structures for GFI
|
|
*
|
|
* Author : Henry Nash + various others
|
|
*
|
|
*/
|
|
|
|
/*
|
|
static char SccsID[]="@(#)gfi.h 1.12 04/08/93 Copyright Insignia Solutions Ltd.";
|
|
*/
|
|
|
|
/*
|
|
* ============================================================================
|
|
* Structure/Data definitions
|
|
* ============================================================================
|
|
*/
|
|
|
|
#define MAX_COMMAND_LEN 9 /* max number of command bytes */
|
|
#define MAX_RESULT_LEN 7 /* max number of result bytes */
|
|
|
|
typedef unsigned char FDC_CMD_BLOCK;
|
|
typedef unsigned char FDC_RESULT_BLOCK;
|
|
|
|
|
|
/* START: FDC COMMAND BLOCK DEFINITIONS >>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
|
|
|
/*
|
|
* A simple access to the command type and drive
|
|
*/
|
|
|
|
/* the command itself */
|
|
#define get_type_cmd(ptr) (ptr[0] & 0x1f)
|
|
#define put_type_cmd(ptr,val) ptr[0] = (ptr[0] & ~0x1f) | ((val << 0) & 0x1f)
|
|
/* ...and the drive no */
|
|
#define get_type_drive(ptr) (ptr[1] & 0x3)
|
|
#define put_type_drive(ptr,val) ptr[1] = (ptr[1] & ~0x3) | ((val << 0) & 0x3)
|
|
|
|
/*
|
|
* Class 0 - read data, read deleted data, all scans
|
|
*/
|
|
|
|
/* multi-track */
|
|
#define get_c0_MT(ptr) ((ptr[0] & 0x80) >> 7)
|
|
#define put_c0_MT(ptr,val) ptr[0] = (ptr[0] & ~0x80) | ((val << 7) & 0x80)
|
|
/* always 1 - FM not used */
|
|
#define get_c0_MFM(ptr) ((ptr[0] & 0x40) >> 6)
|
|
#define put_c0_MFM(ptr,val) ptr[0] = (ptr[0] & ~0x40) | ((val << 6) & 0x40)
|
|
/* skip data */
|
|
#define get_c0_skip(ptr) ((ptr[0] & 0x20) >> 5)
|
|
#define put_c0_skip(ptr,val) ptr[0] = (ptr[0] & ~0x20) | ((val << 5) & 0x20)
|
|
/* the command itself */
|
|
#define get_c0_cmd(ptr) (ptr[0] & 0x1f)
|
|
#define put_c0_cmd(ptr,val) ptr[0] = (ptr[0] & ~0x1f) | ((val << 0) & 0x1f)
|
|
/* padding */
|
|
#define get_c0_pad(ptr) ((ptr[1] & 0xf8) >> 3)
|
|
#define put_c0_pad(ptr,val) ptr[1] = (ptr[1] & ~0xf8) | ((val << 3) & 0xf8)
|
|
/* which head */
|
|
#define get_c0_head(ptr) ((ptr[1] & 0x4) >> 2)
|
|
#define put_c0_head(ptr,val) ptr[1] = (ptr[1] & ~0x4) | ((val << 2) & 0x4)
|
|
/* drive unit */
|
|
#define get_c0_drive(ptr) (ptr[1] & 0x3)
|
|
#define put_c0_drive(ptr,val) ptr[1] = (ptr[1] & ~0x3) | ((val << 0) & 0x3)
|
|
/* cylinder number */
|
|
#define get_c0_cyl(ptr) ptr[2]
|
|
#define put_c0_cyl(ptr,val) ptr[2] = val
|
|
/* head number - again ! */
|
|
#define get_c0_hd(ptr) ptr[3]
|
|
#define put_c0_hd(ptr,val) ptr[3] = val
|
|
/* sector number */
|
|
#define get_c0_sector(ptr) ptr[4]
|
|
#define put_c0_sector(ptr,val) ptr[4] = val
|
|
/* encoded bytes per sector */
|
|
#define get_c0_N(ptr) ptr[5]
|
|
#define put_c0_N(ptr,val) ptr[5] = val
|
|
/* last sector on track */
|
|
#define get_c0_EOT(ptr) ptr[6]
|
|
#define put_c0_EOT(ptr,val) ptr[6] = val
|
|
/* gap length */
|
|
#define get_c0_GPL(ptr) ptr[7]
|
|
#define put_c0_GPL(ptr,val) ptr[7] = val
|
|
/* data length */
|
|
#define get_c0_DTL(ptr) ptr[8]
|
|
#define put_c0_DTL(ptr,val) ptr[8] = val
|
|
|
|
/*
|
|
* Class 1 - write data, write deleted data
|
|
*/
|
|
|
|
/* multi-track */
|
|
#define get_c1_MT(ptr) ((ptr[0] & 0x80) >> 7)
|
|
#define put_c1_MT(ptr,val) ptr[0] = (ptr[0] & ~0x80) | ((val << 7) & 0x80)
|
|
/* always 1 - FM not used */
|
|
#define get_c1_MFM(ptr) ((ptr[0] & 0x40) >> 6)
|
|
#define put_c1_MFM(ptr,val) ptr[0] = (ptr[0] & ~0x40) | ((val << 6) & 0x40)
|
|
/* padding */
|
|
#define get_c1_pad(ptr) ((ptr[0] & 0x20) >> 5)
|
|
#define put_c1_pad(ptr,val) ptr[0] = (ptr[0] & ~0x20) | ((val << 5) & 0x20)
|
|
/* the command itself */
|
|
#define get_c1_cmd(ptr) (ptr[0] & 0x1f)
|
|
#define put_c1_cmd(ptr,val) ptr[0] = (ptr[0] & ~0x1f) | ((val << 0) & 0x1f)
|
|
/* padding */
|
|
#define get_c1_pad1(ptr) ((ptr[1] & 0xf8) >> 3)
|
|
#define put_c1_pad1(ptr,val) ptr[1] = (ptr[1] & ~0xf8) | ((val << 3) & 0xf8)
|
|
/* which head */
|
|
#define get_c1_head(ptr) ((ptr[1] & 0x4) >> 2)
|
|
#define put_c1_head(ptr,val) ptr[1] = (ptr[1] & ~0x4) | ((val << 2) & 0x4)
|
|
/* drive unit */
|
|
#define get_c1_drive(ptr) (ptr[1] & 0x3)
|
|
#define put_c1_drive(ptr,val) ptr[1] = (ptr[1] & ~0x3) | ((val << 0) & 0x3)
|
|
/* cylinder number */
|
|
#define get_c1_cyl(ptr) ptr[2]
|
|
#define put_c1_cyl(ptr,val) ptr[2] = val
|
|
/* head number - again ! */
|
|
#define get_c1_hd(ptr) ptr[3]
|
|
#define put_c1_hd(ptr,val) ptr[3] = val
|
|
/* sector number */
|
|
#define get_c1_sector(ptr) ptr[4]
|
|
#define put_c1_sector(ptr,val) ptr[4] = val
|
|
/* encoded bytes per sector */
|
|
#define get_c1_N(ptr) ptr[5]
|
|
#define put_c1_N(ptr,val) ptr[5] = val
|
|
/* last sector on track */
|
|
#define get_c1_EOT(ptr) ptr[6]
|
|
#define put_c1_EOT(ptr,val) ptr[6] = val
|
|
/* gap length */
|
|
#define get_c1_GPL(ptr) ptr[7]
|
|
#define put_c1_GPL(ptr,val) ptr[7] = val
|
|
/* data length */
|
|
#define get_c1_DTL(ptr) ptr[8]
|
|
#define put_c1_DTL(ptr,val) ptr[8] = val
|
|
|
|
/*
|
|
* Class 2 - read a track
|
|
*/
|
|
|
|
/* always 1 - FM not used */
|
|
#define get_c2_MFM(ptr) ((ptr[0] & 0x40) >> 6)
|
|
#define put_c2_MFM(ptr,val) ptr[0] = (ptr[0] & ~0x40) | ((val << 6) & 0x40)
|
|
/* skip data */
|
|
#define get_c2_skip(ptr) ((ptr[0] & 0x20) >> 5)
|
|
#define put_c2_skip(ptr,val) ptr[0] = (ptr[0] & ~0x20) | ((val << 5) & 0x20)
|
|
/* the command itself */
|
|
#define get_c2_cmd(ptr) (ptr[0] & 0x1f)
|
|
#define put_c2_cmd(ptr,val) ptr[0] = (ptr[0] & ~0x1f) | ((val << 0) & 0x1f)
|
|
/* padding */
|
|
/* padding */
|
|
#define get_c2_pad1(ptr) ((ptr[1] & 0xf8) >> 3)
|
|
#define put_c2_pad1(ptr,val) ptr[1] = (ptr[1] & ~0xf8) | ((val << 3) & 0xf8)
|
|
/* which head */
|
|
#define get_c2_head(ptr) ((ptr[1] & 0x4) >> 2)
|
|
#define put_c2_head(ptr,val) ptr[1] = (ptr[1] & ~0x4) | ((val << 2) & 0x4)
|
|
/* drive unit */
|
|
#define get_c2_drive(ptr) (ptr[1] & 0x3)
|
|
#define put_c2_drive(ptr,val) ptr[1] = (ptr[1] & ~0x3) | ((val << 0) & 0x3)
|
|
/* cylinder number */
|
|
#define get_c2_cyl(ptr) ptr[2]
|
|
#define put_c2_cyl(ptr,val) ptr[2] = val
|
|
/* head number - again ! */
|
|
#define get_c2_hd(ptr) ptr[3]
|
|
#define put_c2_hd(ptr,val) ptr[3] = val
|
|
/* sector number */
|
|
#define get_c2_sector(ptr) ptr[4]
|
|
#define put_c2_sector(ptr,val) ptr[4] = val
|
|
/* encoded bytes per sector */
|
|
#define get_c2_N(ptr) ptr[5]
|
|
#define put_c2_N(ptr,val) ptr[5] = val
|
|
/* last sector on track */
|
|
#define get_c2_EOT(ptr) ptr[6]
|
|
#define put_c2_EOT(ptr,val) ptr[6] = val
|
|
/* gap length */
|
|
#define get_c2_GPL(ptr) ptr[7]
|
|
#define put_c2_GPL(ptr,val) ptr[7] = val
|
|
/* data length */
|
|
#define get_c2_DTL(ptr) ptr[8]
|
|
#define put_c2_DTL(ptr,val) ptr[8] = val
|
|
|
|
/*
|
|
* Class 3 - format a track
|
|
*/
|
|
|
|
/* padding */
|
|
#define get_c3_pad(ptr) ((ptr[0] & 0x80) >> 7)
|
|
#define put_c3_pad(ptr,val) ptr[0] = (ptr[0] & ~0x80) | ((val << 7) & 0x80)
|
|
/* always 1 - FM not used */
|
|
#define get_c3_MFM(ptr) ((ptr[0] & 0x40) >> 6)
|
|
#define put_c3_MFM(ptr,val) ptr[0] = (ptr[0] & ~0x40) | ((val << 6) & 0x40)
|
|
/* padding */
|
|
#define get_c3_pad1(ptr) ((ptr[0] & 0x20) >> 5)
|
|
#define put_c3_pad1(ptr,val) ptr[0] = (ptr[0] & ~0x20) | ((val << 5) & 0x20)
|
|
/* the command itself */
|
|
#define get_c3_cmd(ptr) (ptr[0] & 0x1f)
|
|
#define put_c3_cmd(ptr,val) ptr[0] = (ptr[0] & ~0x1f) | ((val << 0) & 0x1f)
|
|
/* padding */
|
|
#define get_c3_pad2(ptr) ((ptr[1] & 0xf8) >> 3)
|
|
#define put_c3_pad2(ptr,val) ptr[1] = (ptr[1] & ~0xf8) | ((val << 3) & 0xf8)
|
|
/* which head */
|
|
#define get_c3_head(ptr) ((ptr[1] & 0x4) >> 2)
|
|
#define put_c3_head(ptr,val) ptr[1] = (ptr[1] & ~0x4) | ((val << 2) & 0x4)
|
|
/* drive unit */
|
|
#define get_c3_drive(ptr) (ptr[1] & 0x3)
|
|
#define put_c3_drive(ptr,val) ptr[1] = (ptr[1] & ~0x3) | ((val << 0) & 0x3)
|
|
/* encoded bytes per sector */
|
|
#define get_c3_N(ptr) ptr[2]
|
|
#define put_c3_N(ptr,val) ptr[2] = val
|
|
/* sectors per cylinder */
|
|
#define get_c3_SC(ptr) ptr[3]
|
|
#define put_c3_SC(ptr,val) ptr[3] = val
|
|
/* gap length */
|
|
#define get_c3_GPL(ptr) ptr[4]
|
|
#define put_c3_GPL(ptr,val) ptr[4] = val
|
|
/* filler byte */
|
|
#define get_c3_filler(ptr) ptr[5]
|
|
#define put_c3_filler(ptr,val) ptr[5] = val
|
|
|
|
/*
|
|
* Class 4 - read ID
|
|
*/
|
|
|
|
/* padding */
|
|
#define get_c4_pad(ptr) ((ptr[0] & 0x80) >> 7)
|
|
#define put_c4_pad(ptr,val) ptr[0] = (ptr[0] & ~0x80) | ((val << 7) & 0x80)
|
|
/* always 1 - FM not used */
|
|
#define get_c4_MFM(ptr) ((ptr[0] & 0x40) >> 6)
|
|
#define put_c4_MFM(ptr,val) ptr[0] = (ptr[0] & ~0x40) | ((val << 6) & 0x40)
|
|
/* padding */
|
|
#define get_c4_pad1(ptr) ((ptr[0] & 0x20) >> 5)
|
|
#define put_c4_pad1(ptr,val) ptr[0] = (ptr[0] & ~0x20) | ((val << 5) & 0x20)
|
|
/* the command itself */
|
|
#define get_c4_cmd(ptr) (ptr[0] & 0x1f)
|
|
#define put_c4_cmd(ptr,val) ptr[0] = (ptr[0] & ~0x1f) | ((val << 0) & 0x1f)
|
|
/* padding */
|
|
#define get_c4_pad2(ptr) ((ptr[1] & 0xf8) >> 3)
|
|
#define put_c4_pad2(ptr,val) ptr[1] = (ptr[1] & ~0xf8) | ((val << 3) & 0xf8)
|
|
/* which head */
|
|
#define get_c4_head(ptr) ((ptr[1] & 0x4) >> 2)
|
|
#define put_c4_head(ptr,val) ptr[1] = (ptr[1] & ~0x4) | ((val << 2) & 0x4)
|
|
/* drive unit */
|
|
#define get_c4_drive(ptr) (ptr[1] & 0x3)
|
|
#define put_c4_drive(ptr,val) ptr[1] = (ptr[1] & ~0x3) | ((val << 0) & 0x3)
|
|
|
|
/*
|
|
* Class 5 - recalibrate
|
|
*/
|
|
|
|
/* padding */
|
|
#define get_c5_pad(ptr) ((ptr[0] & 0xe0) >> 5)
|
|
#define put_c5_pad(ptr,val) ptr[0] = (ptr[0] & ~0xe0) | ((val << 5) & 0xe0)
|
|
/* the command itself */
|
|
#define get_c5_cmd(ptr) (ptr[0] & 0x1f)
|
|
#define put_c5_cmd(ptr,val) ptr[0] = (ptr[0] & ~0x1f) | ((val << 0) & 0x1f)
|
|
/* padding */
|
|
#define get_c5_pad1(ptr) ((ptr[1] & 0xfc) >> 2)
|
|
#define put_c5_pad1(ptr,val) ptr[1] = (ptr[1] & ~0xfc) | ((val << 2) & 0xfc)
|
|
/* drive unit */
|
|
#define get_c5_drive(ptr) (ptr[1] & 0x3)
|
|
#define put_c5_drive(ptr,val) ptr[1] = (ptr[1] & ~0x3) | ((val << 0) & 0x3)
|
|
|
|
/*
|
|
* Class 6 - specify
|
|
*/
|
|
|
|
/* the command itself */
|
|
#define get_c6_cmd(ptr) (ptr[0] & 0x1f)
|
|
#define put_c6_cmd(ptr,val) ptr[0] = (ptr[0] & ~0x1f) | ((val << 0) & 0x1f)
|
|
/* step rate time */
|
|
#define get_c6_SRT(ptr) ((ptr[1] & 0xf0) >> 4)
|
|
#define put_c6_SRT(ptr,val) ptr[1] = (ptr[1] & ~0xf0) | ((val << 4) & 0xf0)
|
|
/* head unload time */
|
|
#define get_c6_HUT(ptr) (ptr[1] & 0xf)
|
|
#define put_c6_HUT(ptr,val) ptr[1] = (ptr[1] & ~0xf) | ((val << 0) & 0xf)
|
|
/* head load time */
|
|
#define get_c6_HLT(ptr) ((ptr[2] & 0xfe) >> 1)
|
|
#define put_c6_HLT(ptr,val) ptr[2] = (ptr[2] & ~0xfe) | ((val << 1) & 0xfe)
|
|
/* non-dma mode - not supp. */
|
|
#define get_c6_ND(ptr) (ptr[2] & 0x1)
|
|
#define put_c6_ND(ptr,val) ptr[2] = (ptr[2] & ~0x1) | ((val << 0) & 0x1)
|
|
|
|
/*
|
|
* Class 7 - sense drive status
|
|
*/
|
|
|
|
/* the command itself */
|
|
#define get_c7_cmd(ptr) (ptr[0] & 0x1f)
|
|
#define put_c7_cmd(ptr,val) ptr[0] = (ptr[0] & ~0x1f) | ((val << 0) & 0x1f)
|
|
/* which head */
|
|
#define get_c7_head(ptr) ((ptr[1] & 0x4) >> 2)
|
|
#define put_c7_head(ptr,val) ptr[1] = (ptr[1] & ~0x4) | ((val << 2) & 0x4)
|
|
/* drive unit */
|
|
#define get_c7_drive(ptr) (ptr[1] & 0x3)
|
|
#define put_c7_drive(ptr,val) ptr[1] = (ptr[1] & ~0x3) | ((val << 0) & 0x3)
|
|
|
|
/*
|
|
* Class 8 - seek
|
|
*/
|
|
|
|
/* padding */
|
|
#define get_c8_pad(ptr) ((ptr[0] & 0xe0) >> 5)
|
|
#define put_c8_pad(ptr,val) ptr[0] = (ptr[0] & ~0xe0) | ((val << 5) & 0xe0)
|
|
/* the command itself */
|
|
#define get_c8_cmd(ptr) (ptr[0] & 0x1f)
|
|
#define put_c8_cmd(ptr,val) ptr[0] = (ptr[0] & ~0x1f) | ((val << 0) & 0x1f)
|
|
/* padding */
|
|
#define get_c8_pad1(ptr) ((ptr[1] & 0xf8) >> 3)
|
|
#define put_c8_pad1(ptr,val) ptr[1] = (ptr[1] & ~0xf8) | ((val << 3) & 0xf8)
|
|
/* which head */
|
|
#define get_c8_head(ptr) ((ptr[1] & 0x4) >> 2)
|
|
#define put_c8_head(ptr,val) ptr[1] = (ptr[1] & ~0x4) | ((val << 2) & 0x4)
|
|
/* drive unit */
|
|
#define get_c8_drive(ptr) (ptr[1] & 0x3)
|
|
#define put_c8_drive(ptr,val) ptr[1] = (ptr[1] & ~0x3) | ((val << 0) & 0x3)
|
|
/* new cylinder no for seek */
|
|
#define get_c8_new_cyl(ptr) ptr[2]
|
|
#define put_c8_new_cyl(ptr,val) ptr[2] = val
|
|
|
|
/* END: FDC COMMAND BLOCK DEFINITIONS <<<<<<<<<<<<<<<<<<<<<<<<<<< */
|
|
|
|
/* START: FDC RESULT BLOCK DEFINITIONS >>>>>>>>>>>>>>>>>>>>>>>>>>>> */
|
|
|
|
/*
|
|
* Class 0 - read/write data, read/write deleted data,
|
|
* all scans, read/format a track
|
|
*/
|
|
|
|
/* status register 0 */
|
|
#define get_r0_ST0(ptr) ptr[0]
|
|
#define put_r0_ST0(ptr,val) ptr[0] = val
|
|
/* status register 1 */
|
|
#define get_r0_ST1(ptr) ptr[1]
|
|
#define put_r0_ST1(ptr,val) ptr[1] = val
|
|
/* status register 2 */
|
|
#define get_r0_ST2(ptr) ptr[2]
|
|
#define put_r0_ST2(ptr,val) ptr[2] = val
|
|
/* cylinder number */
|
|
#define get_r0_cyl(ptr) ptr[3]
|
|
#define put_r0_cyl(ptr,val) ptr[3] = val
|
|
/* head number */
|
|
#define get_r0_head(ptr) ptr[4]
|
|
#define put_r0_head(ptr,val) ptr[4] = val
|
|
/* sector number */
|
|
#define get_r0_sector(ptr) ptr[5]
|
|
#define put_r0_sector(ptr,val) ptr[5] = val
|
|
/* encoded bytes per sector if N == 0 */
|
|
#define get_r0_N(ptr) ptr[6]
|
|
#define put_r0_N(ptr,val) ptr[6] = val
|
|
|
|
/*
|
|
* Class 1 - a split up way of looking at Status registers
|
|
* ST0 to ST2.
|
|
*/
|
|
|
|
/* Termination code */
|
|
#define get_r1_ST0_int_code(ptr) ((ptr[0] & 0xc0) >> 6)
|
|
#define put_r1_ST0_int_code(ptr,val) ptr[0] = (ptr[0] & ~0xc0) | ((val << 6) & 0xc0)
|
|
/* End of seek cmd */
|
|
#define get_r1_ST0_seek_end(ptr) ((ptr[0] & 0x20) >> 5)
|
|
#define put_r1_ST0_seek_end(ptr,val) ptr[0] = (ptr[0] & ~0x20) | ((val << 5) & 0x20)
|
|
/* Equipment fault */
|
|
#define get_r1_ST0_equipment(ptr) ((ptr[0] & 0x10) >> 4)
|
|
#define put_r1_ST0_equipment(ptr,val) ptr[0] = (ptr[0] & ~0x10) | ((val << 4) & 0x10)
|
|
/* Device not ready */
|
|
#define get_r1_ST0_not_ready(ptr) ((ptr[0] & 0x8) >> 3)
|
|
#define put_r1_ST0_not_ready(ptr,val) ptr[0] = (ptr[0] & ~0x8) | ((val << 3) & 0x8)
|
|
/* State of head */
|
|
#define get_r1_ST0_head_address(ptr) ((ptr[0] & 0x4) >> 2)
|
|
#define put_r1_ST0_head_address(ptr,val) ptr[0] = (ptr[0] & ~0x4) | ((val << 2) & 0x4)
|
|
/* Which drive */
|
|
#define get_r1_ST0_unit(ptr) (ptr[0] & 0x3)
|
|
#define put_r1_ST0_unit(ptr,val) ptr[0] = (ptr[0] & ~0x3) | ((val << 0) & 0x3)
|
|
/* Access off end of cylinder */
|
|
#define get_r1_ST1_end_of_cylinder(ptr) ((ptr[1] & 0x80) >> 7)
|
|
#define put_r1_ST1_end_of_cylinder(ptr,val) ptr[1] = (ptr[1] & ~0x80) | ((val << 7) & 0x80)
|
|
/* CRC error in data field/ID */
|
|
#define get_r1_ST1_data_error(ptr) ((ptr[1] & 0x20) >> 5)
|
|
#define put_r1_ST1_data_error(ptr,val) ptr[1] = (ptr[1] & ~0x20) | ((val << 5) & 0x20)
|
|
/* timeout of device */
|
|
#define get_r1_ST1_over_run(ptr) ((ptr[1] & 0x10) >> 4)
|
|
#define put_r1_ST1_over_run(ptr,val) ptr[1] = (ptr[1] & ~0x10) | ((val << 4) & 0x10)
|
|
/* sector not found */
|
|
#define get_r1_ST1_no_data(ptr) ((ptr[1] & 0x4) >> 2)
|
|
#define put_r1_ST1_no_data(ptr,val) ptr[1] = (ptr[1] & ~0x4) | ((val << 2) & 0x4)
|
|
/* write protected */
|
|
#define get_r1_ST1_write_protected(ptr) ((ptr[1] & 0x2) >> 1)
|
|
#define put_r1_ST1_write_protected(ptr,val) ptr[1] = (ptr[1] & ~0x2) | ((val << 1) & 0x2)
|
|
/* Cannot find adress mask/ID */
|
|
#define get_r1_ST1_no_address_mark(ptr) (ptr[1] & 0x1)
|
|
#define put_r1_ST1_no_address_mark(ptr,val) ptr[1] = (ptr[1] & ~0x1) | ((val << 0) & 0x1)
|
|
/* Deleted data found in Read/Scan */
|
|
#define get_r1_ST2_control_mark(ptr) ((ptr[2] & 0x40) >> 6)
|
|
#define put_r1_ST2_control_mark(ptr,val) ptr[2] = (ptr[2] & ~0x40) | ((val << 6) & 0x40)
|
|
/* CRC error in data field */
|
|
#define get_r1_ST2_data_field_error(ptr) ((ptr[2] & 0x20) >> 5)
|
|
#define put_r1_ST2_data_field_error(ptr,val) ptr[2] = (ptr[2] & ~0x20) | ((val << 5) & 0x20)
|
|
/* cylinder miss-match */
|
|
#define get_r1_ST2_wrong_cyclinder(ptr) ((ptr[2] & 0x10) >> 4)
|
|
#define put_r1_ST2_wrong_cyclinder(ptr,val) ptr[2] = (ptr[2] & ~0x10) | ((val << 4) & 0x10)
|
|
/* Match found in scan */
|
|
#define get_r1_ST2_scan_equal_hit(ptr) ((ptr[2] & 0x8) >> 3)
|
|
#define put_r1_ST2_scan_equal_hit(ptr,val) ptr[2] = (ptr[2] & ~0x8) | ((val << 3) & 0x8)
|
|
/* Sector not found during scan command */
|
|
#define get_r1_ST2_scan_not_satisfied(ptr) ((ptr[2] & 0x4) >> 2)
|
|
#define put_r1_ST2_scan_not_satisfied(ptr,val) ptr[2] = (ptr[2] & ~0x4) | ((val << 2) & 0x4)
|
|
/* Invalid cylinder found */
|
|
#define get_r1_ST2_bad_cylinder(ptr) ((ptr[2] & 0x2) >> 1)
|
|
#define put_r1_ST2_bad_cylinder(ptr,val) ptr[2] = (ptr[2] & ~0x2) | ((val << 1) & 0x2)
|
|
/* Missing Address mark */
|
|
#define get_r1_ST2_no_address_mark(ptr) (ptr[2] & 0x1)
|
|
#define put_r1_ST2_no_address_mark(ptr,val) ptr[2] = (ptr[2] & ~0x1) | ((val << 0) & 0x1)
|
|
|
|
/*
|
|
* Class 2 - sense drive status
|
|
*/
|
|
|
|
/* Device fault */
|
|
#define get_r2_ST3_fault(ptr) ((ptr[0] & 0x80) >> 7)
|
|
#define put_r2_ST3_fault(ptr,val) ptr[0] = (ptr[0] & ~0x80) | ((val << 7) & 0x80)
|
|
/* Write protected diskette */
|
|
#define get_r2_ST3_write_protected(ptr) ((ptr[0] & 0x40) >> 6)
|
|
#define put_r2_ST3_write_protected(ptr,val) ptr[0] = (ptr[0] & ~0x40) | ((val << 6) & 0x40)
|
|
/* Device is ready */
|
|
#define get_r2_ST3_ready(ptr) ((ptr[0] & 0x20) >> 5)
|
|
#define put_r2_ST3_ready(ptr,val) ptr[0] = (ptr[0] & ~0x20) | ((val << 5) & 0x20)
|
|
/* Track zero found */
|
|
#define get_r2_ST3_track_0(ptr) ((ptr[0] & 0x10) >> 4)
|
|
#define put_r2_ST3_track_0(ptr,val) ptr[0] = (ptr[0] & ~0x10) | ((val << 4) & 0x10)
|
|
/* Double sided diskette */
|
|
#define get_r2_ST3_two_sided(ptr) ((ptr[0] & 0x8) >> 3)
|
|
#define put_r2_ST3_two_sided(ptr,val) ptr[0] = (ptr[0] & ~0x8) | ((val << 3) & 0x8)
|
|
/* Side address signal */
|
|
#define get_r2_ST3_head_address(ptr) ((ptr[0] & 0x4) >> 2)
|
|
#define put_r2_ST3_head_address(ptr,val) ptr[0] = (ptr[0] & ~0x4) | ((val << 2) & 0x4)
|
|
/* Which unit is selected */
|
|
#define get_r2_ST3_unit(ptr) (ptr[0] & 0x3)
|
|
#define put_r2_ST3_unit(ptr,val) ptr[0] = (ptr[0] & ~0x3) | ((val << 0) & 0x3)
|
|
|
|
/*
|
|
* Class 3 - sense interrupt status
|
|
*/
|
|
|
|
/* status register 0 */
|
|
#define get_r3_ST0(ptr) ptr[0]
|
|
#define put_r3_ST0(ptr,val) ptr[0] = val
|
|
/* present cylinder number */
|
|
#define get_r3_PCN(ptr) ptr[1]
|
|
#define put_r3_PCN(ptr,val) ptr[1] = val
|
|
|
|
/*
|
|
* Class 4 - invalid codes
|
|
*/
|
|
|
|
/* status register 0 */
|
|
#define get_r4_ST0(ptr) ptr[0]
|
|
#define put_r4_ST0(ptr,val) ptr[0] = val
|
|
|
|
/* END: FDC RESULT BLOCK DEFINITIONS <<<<<<<<<<<<<<<<<<<<<<<<<<<< */
|
|
|
|
|
|
/*
|
|
* An entry data structure that holds information describing the number of bytes
|
|
* in the fdc command/result phases. The index is the fdc command code, see
|
|
* the INTEL Application note on the 8272A for a full description.
|
|
*
|
|
* The "result_byte" is the number of bytes in the standard FDC result phase
|
|
* while "gfi_result_byte" is the number of bytes in the pseudo result phase
|
|
* used by GFI and its server modules (ie some commands that do not normally
|
|
* have a result phase, use an implicit Sense Interrupt Status result phase).
|
|
*/
|
|
|
|
typedef struct {
|
|
half_word cmd_bytes; /* number of command bytes */
|
|
half_word result_bytes; /* number of result bytes */
|
|
half_word gfi_result_bytes; /* number of GFI result bytes */
|
|
half_word cmd_class; /* class of the command */
|
|
half_word result_class; /* class of the result */
|
|
boolean dma_required; /* dma required ? */
|
|
boolean int_required; /* interrupts required ? */
|
|
} FDC_DATA_ENTRY;
|
|
|
|
|
|
/*
|
|
* The following list the error codes that the GFI commands (see gfi.f) can
|
|
* return. 0 is considered to be success.
|
|
*/
|
|
|
|
#define GFI_PROTOCOL_ERROR 1
|
|
#define GFI_FDC_TIMEOUT 2
|
|
#define GFI_FDC_LOGICAL_ERROR 3
|
|
|
|
/*
|
|
* GFI Drive types
|
|
*/
|
|
|
|
#define GFI_DRIVE_TYPE_NULL 0 /* unidentified */
|
|
#define GFI_DRIVE_TYPE_360 1 /* 360K 5.25" */
|
|
#define GFI_DRIVE_TYPE_12 2 /* 1.2M 5.25" */
|
|
#define GFI_DRIVE_TYPE_720 3 /* 720K 3.5" */
|
|
#define GFI_DRIVE_TYPE_144 4 /* 1.44M 3.5" */
|
|
#define GFI_DRIVE_TYPE_288 5 /* 2.88M 3.5" */
|
|
|
|
#ifdef NTVDM
|
|
#define GFI_DRIVE_TYPE_MAX 6
|
|
#endif
|
|
|
|
|
|
/***************************************************************************
|
|
**
|
|
** Definitions and prototypes for the gfi_function_table,
|
|
** the functions therein, and the orthogonal floppy interface functions.
|
|
** Using the typedef'd prototypes should make it much easier to avoid
|
|
** definition clashes.
|
|
** This is now the only base floppy header file, and if you use the
|
|
** generic unix_flop.c module, the only floppy header anywhere. The generic
|
|
** code is meant to help a new unix port get quick floppy support; it is
|
|
** not meant to replace fancy host floppy code.
|
|
** The improvements that I have made to the floppy system in general are
|
|
** also supposed to make life easier.
|
|
**
|
|
** GM.
|
|
****************************************************************************
|
|
**
|
|
**
|
|
**
|
|
** The GFI has a structure containing pointers to functions that provide
|
|
** the diskette support for all possible drives (0-1) and drive types.
|
|
** Each floppy emmulator module has a function for loading this table
|
|
** with the module's own local functions which can then be used by the
|
|
** gfi system to emmulate the sort of device the module was designed for.
|
|
**
|
|
** This table (of two structures - one for each possible drive)
|
|
** is of course GLOBAL.
|
|
**
|
|
** The structure has the following fields:
|
|
**
|
|
** The GFI command function: GFI_FUNC_ENTRY.command_fn,
|
|
** The GFI drive on function: GFI_FUNC_ENTRY.drive_on_fn,
|
|
** The GFI drive off function: GFI_FUNC_ENTRY.drive_off_fn,
|
|
** The GFI reset function: GFI_FUNC_ENTRY.reset_fn,
|
|
** The GFI set high density function: GFI_FUNC_ENTRY.high_fn,
|
|
** The GFI drive type function: GFI_FUNC_ENTRY.drive_type_fn,
|
|
** The GFI disk changed function: GFI_FUNC_ENTRY.change_fn
|
|
**
|
|
** Structure definition:
|
|
** -----------------------
|
|
*/
|
|
typedef struct
|
|
{
|
|
SHORT (*command_fn) IPT2( FDC_CMD_BLOCK *, ip, FDC_RESULT_BLOCK *, res );
|
|
SHORT (*drive_on_fn) IPT1( UTINY, drive );
|
|
SHORT (*drive_off_fn) IPT1( UTINY, drive );
|
|
SHORT (*reset_fn) IPT2( FDC_RESULT_BLOCK *, res, UTINY, drive );
|
|
SHORT (*high_fn) IPT2( UTINY, drive, half_word, n);
|
|
SHORT (*drive_type_fn) IPT1( UTINY, drive );
|
|
SHORT (*change_fn) IPT1( UTINY, drive );
|
|
|
|
} GFI_FUNCTION_ENTRY;
|
|
|
|
/*
|
|
** ============================================================================
|
|
** External declarations and macros
|
|
** ============================================================================
|
|
**
|
|
**
|
|
**
|
|
** The data structure describing the fdc command/result phases, and the
|
|
** function pointer table set up by calls to the individual init functions
|
|
** in each of the GFI server modules.
|
|
**
|
|
**
|
|
**
|
|
** These tables are in gfi.c
|
|
*/
|
|
IMPORT GFI_FUNCTION_ENTRY gfi_function_table[];
|
|
IMPORT FDC_DATA_ENTRY gfi_fdc_description[];
|
|
/*
|
|
** The following functions form the interface between the GFI system
|
|
** and the floppy module (whichever). They are global, but the only access
|
|
** to the other functions gfi needs is via the gfi_function_table.
|
|
*/
|
|
|
|
IMPORT SHORT host_gfi_rdiskette_valid
|
|
IPT3(UTINY,hostID,ConfigValues *,vals,CHAR *,err);
|
|
|
|
IMPORT SHORT host_gfi_rdiskette_active
|
|
IPT3(UTINY, hostID, BOOL, active, CHAR, *err);
|
|
|
|
IMPORT SHORT gfi_empty_active
|
|
IPT3(UTINY, hostID, BOOL, active, CHAR, *err);
|
|
|
|
IMPORT VOID host_gfi_rdiskette_change
|
|
IPT2(UTINY, hostID, BOOL, apply);
|
|
|
|
#ifndef host_rflop_drive_type
|
|
/* new function to say what kind of drive we have
|
|
*/
|
|
IMPORT SHORT host_rflop_drive_type IPT2 (INT, fd, CHAR *, name);
|
|
#endif /* host_rflop_drive_type */
|
|
|
|
/* The gfi global functions. These need to be global because they are the
|
|
** interface to the private host dependant floppy functions. Each one does
|
|
** little more than call the real function via the table.
|
|
*/
|
|
/* The gfi_reset is special; not the same as the other floppy inits because
|
|
** it is called from main() to startup the gfi system by making both drives
|
|
** 'empty'. This means that it has no drive parameter.
|
|
*/
|
|
|
|
IMPORT SHORT gfi_drive_on IPT1( UTINY, drive );
|
|
IMPORT SHORT gfi_drive_off IPT1( UTINY, drive );
|
|
IMPORT SHORT gfi_low IPT1( UTINY, drive );
|
|
IMPORT SHORT gfi_drive_type IPT1( UTINY, drive );
|
|
IMPORT SHORT gfi_change IPT1( UTINY, drive );
|
|
IMPORT VOID gfi_init IPT0();
|
|
IMPORT SHORT gfi_reset IPT2( FDC_RESULT_BLOCK *, res, UTINY, drive );
|
|
IMPORT SHORT gfi_high IPT2( UTINY, drive, half_word, n);
|
|
IMPORT SHORT gfi_fdc_command IPT2( FDC_CMD_BLOCK *, ip, FDC_RESULT_BLOCK *, res );
|