1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
|
/* Copyright (c) 2000, Timothy Mann */
/* $Id: trs_hard.h,v 1.6 2009/06/15 23:41:03 mann Exp $ */
/* This software may be copied, modified, and used for any purpose
* without fee, provided that (1) the above copyright notice is
* retained, and (2) modified versions are clearly marked as having
* been modified, with the modifier's name and the date included. */
/*
* Definitions for the Radio Shack TRS-80 Model I/III/4/4P
* hard disk controller. This is a Western Digital WD1000/WD1010
* mapped at ports 0xc8-0xcf, plus control registers at 0xc0-0xc1.
*
* Definitions inferred from various drivers and sketchy documents
* found in odd corners. Anyone have a real WD10xx data sheet?
*/
extern void trs_hard_init(void);
extern int trs_hard_in(int port);
extern void trs_hard_out(int port, int value);
extern char* trs_disk_dir;
/* Sector size is always 256 for TRSDOS/LDOS/etc. */
/* Other sizes currently not emulated */
#define TRS_HARD_SECSIZE 256
#define TRS_HARD_SECSIZE_CODE 0x0f /* size code for 256 byte sectors?!! */
/* RSHARD assumes 32 sectors/track */
/* Other sizes currently not emulated */
#define TRS_HARD_SEC_PER_TRK 32
/*
* Tandy-specific registers
*/
/* Write protect switch register (read only):
* abcd--pi
* a = drive 0 write protected
* b = drive 1 write protected
* c = drive 2 write protected
* d = drive 3 write protected
* p = at least one drive write protected
* i = interrupt request
*/
#define TRS_HARD_WP 0xc0
#define TRS_HARD_WPBIT(d) (0x80 >> (d))
#define TRS_HARD_WPSOME 0x02
#define TRS_HARD_INTRQ 0x01 /* not emulated */
/* Control register (read(?)/write):
* ---sdw--
* s = software reset
* d = device enable
* w = wait enable
*/
#define TRS_HARD_CONTROL 0xc1
#define TRS_HARD_SOFTWARE_RESET 0x10
#define TRS_HARD_DEVICE_ENABLE 0x08
#define TRS_HARD_WAIT_ENABLE 0x04
/* ID register (Model II only!)
*/
#define TRS_HARD_ID0 0xc2
#define TRS_HARD_ID1 0xc3
/* CTC channels (Model II only!)
*/
#define TRS_HARD_CTC0 0xc4
#define TRS_HARD_CTC1 0xc5
#define TRS_HARD_CTC2 0xc6
#define TRS_HARD_CTC3 0xc7
/*
* WD1010 registers
*/
/* Data register (read/write) */
#define TRS_HARD_DATA 0xc8
/* Error register (read only):
* bdin-atm
* b = block marked bad
* e = uncorrectable error in data
* i = uncorrectable error in id (unused?)
* n = id not found
* - = unused
* a = command aborted
* t = track 0 not found
* m = bad address mark
*/
#define TRS_HARD_ERROR (TRS_HARD_DATA+1)
#define TRS_HARD_BBDERR 0x80
#define TRS_HARD_DATAERR 0x40
#define TRS_HARD_IDERR 0x20 /* unused? */
#define TRS_HARD_NFERR 0x10
#define TRS_HARD_MCRERR 0x08 /* unused */
#define TRS_HARD_ABRTERR 0x04
#define TRS_HARD_TRK0ERR 0x02
#define TRS_HARD_MARKERR 0x01
/* Write precompensation register (write only) */
/* Value *4 is the starting cylinder for write precomp */
#define TRS_HARD_PRECOMP (TRS_HARD_DATA+1)
/* Sector count register (read/write) */
/* Used only for multiple sector accesses; otherwise ignored. */
/* Autodecrements when used. */
#define TRS_HARD_SECCNT (TRS_HARD_DATA+2)
/* Sector number register (read/write) */
#define TRS_HARD_SECNUM (TRS_HARD_DATA+3)
/* Cylinder low byte register (read/write) */
#define TRS_HARD_CYLLO (TRS_HARD_DATA+4)
/* Cylinder high byte register (read/write) */
#define TRS_HARD_CYLHI (TRS_HARD_DATA+5)
/* Size/drive/head register (read/write):
* essddhhh
* e = 0 if CRCs used; 1 if ECC used
* ss = sector size; 00=256, 01=512, 10=1024, 11=128
* dd = drive
* hhh = head
*/
#define TRS_HARD_SDH (TRS_HARD_DATA+6)
#define TRS_HARD_ECCMASK 0x80
#define TRS_HARD_ECCSHIFT 7
#define TRS_HARD_SIZEMASK 0x60
#define TRS_HARD_SIZESHIFT 5
#define TRS_HARD_DRIVEMASK 0x18
#define TRS_HARD_DRIVESHIFT 3
#define TRS_HARD_MAXDRIVES 4
#define TRS_HARD_HEADMASK 0x07
#define TRS_HARD_HEADSHIFT 0
#define TRS_HARD_MAXHEADS 8
/* Status register (read only):
* brwsdcie
* b = busy
* r = drive ready
* w = write error
* s = seek complete
* d = data request
* c = corrected ecc (reserved)
* i = command in progress (=software reset required)
* e = error
*/
#define TRS_HARD_STATUS (TRS_HARD_DATA+7)
#define TRS_HARD_BUSY 0x80
#define TRS_HARD_READY 0x40
#define TRS_HARD_WRERR 0x20
#define TRS_HARD_SEEKDONE 0x10
#define TRS_HARD_DRQ 0x08
#define TRS_HARD_ECC 0x04
#define TRS_HARD_CIP 0x02
#define TRS_HARD_ERR 0x01
/* Command register (write only) */
#define TRS_HARD_COMMAND (TRS_HARD_DATA+7)
/*
* WD1010 commands
*/
#define TRS_HARD_CMDMASK 0xf0
/* Restore:
* 0001rrrr
* rrrr = step rate; 0000=35us, else rrrr*0.5ms
*/
#define TRS_HARD_RESTORE 0x10
/* Read sector:
* 0010dm00
* d = 0 for interrupt on DRQ, 1 for interrupt at end (DMA style)
* TRS-80 always uses programmed I/O, INTRQ not connected, I believe.
* m = multiple sector flag (not emulated!)
*/
#define TRS_HARD_READ 0x20
#define TRS_HARD_DMA 0x08
#define TRS_HARD_MULTI 0x04
/* Write sector:
* 00110m00
* m = multiple sector flag (not emulated!)
*/
#define TRS_HARD_WRITE 0x30
/* Verify sector (or "Scan ID"):
* 01000000
*/
#define TRS_HARD_VERIFY 0x40
/* Format track:
* 01010000
*/
#define TRS_HARD_FORMAT 0x50
/* Init (??):
* 01100000
*/
#define TRS_HARD_INIT 0x60
/* Seek to specified sector/head/cylinder:
* 0111rrrr
* rrrr = step rate; 0000=35us, else rrrr*0.5ms
*/
#define TRS_HARD_SEEK 0x70
|