1 /* 2 * ReactOS Floppy Driver 3 * Copyright (C) 2004, Vizzini (vizzini@plasmic.com) 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * PROJECT: ReactOS Floppy Driver 20 * FILE: hardware.h 21 * PURPOSE: Header for FDC control routines 22 * PROGRAMMER: Vizzini (vizzini@plasmic.com) 23 * REVISIONS: 24 * 15-Feb-2004 vizzini - Created 25 * 26 * NOTES: 27 * - Baesd on http://www.nondot.org/sabre/os/files/Disk/FLOPPY.TXT 28 * - Some information taken from Intel 82077AA data sheet (order #290166-007) 29 * - Some definitions are PS/2-Specific; others include the original NEC PD765 30 * - Other information gathered from the comments in the NT 3.5 floppy driver 31 * 32 * TODO: 33 * - Convert these numbers to 100% absolute values; eliminate bit positions 34 * in favor of shifts or bitfields 35 */ 36 37 #pragma once 38 39 #define FLOPPY_DEFAULT_IRQ 0x6 40 #define FDC_PORT_BYTES 0x8 41 42 /* Register offsets from base address (usually 0x3f8) */ 43 #define STATUS_REGISTER_A 0x0 /* Read; PS/2 Only */ 44 #define STATUS_REGISTER_B 0x1 /* Read; PS/2 Only */ 45 #define DIGITAL_OUTPUT_REGISTER 0x2 /* Read/Write */ 46 #define TAPE_DRIVE_REGISTER 0x3 /* Read/Write */ 47 #define MAIN_STATUS_REGISTER 0x4 /* Read */ 48 #define DATA_RATE_SELECT_REGISTER 0x4 /* Write */ 49 #define FIFO 0x5 /* Read/Write */ 50 #define RESERVED_REGISTER 0x6 /* Reserved */ 51 #define DIGITAL_INPUT_REGISTER 0x7 /* Read; PS/2 Only */ 52 #define CONFIGURATION_CONTROL_REGISTER 0x7 /* Write; PS/2 Only */ 53 54 /* STATUS_REGISTER_A */ 55 #define DSRA_DIRECTION 0x1 56 #define DSRA_WRITE_PROTECT 0x2 57 #define DSRA_INDEX 0x4 58 #define DSRA_HEAD_1_SELECT 0x8 59 #define DSRA_TRACK_0 0x10 60 #define DSRA_STEP 0x20 61 #define DSRA_SECOND_DRIVE_INSTALLED 0x40 62 #define DSRA_INTERRUPT_PENDING 0x80 63 64 /* STATUS_REGISTER_B */ 65 #define DSRB_MOTOR_ENABLE_0 0x1 66 #define DSRB_MOTOR_ENABLE_1 0x2 67 #define DSRB_WRITE_ENABLE 0x4 68 #define DSRB_READ_DATA 0x8 69 #define DSRB_WRITE_DATA 0x10 70 #define DSRB_DRIVE_SELECT 0x20 71 72 /* DIGITAL_OUTPUT_REGISTER */ 73 #define DOR_FLOPPY_DRIVE_SELECT 0x3 /* Covers 2 bits, defined below */ 74 #define DOR_FDC_ENABLE 0x4 /* from the website */ 75 #define DOR_RESET 0x4 /* from the Intel guide; 0 = resetting, 1 = enabled */ 76 #define DOR_DMA_IO_INTERFACE_ENABLE 0x8 /* Reserved on PS/2 */ 77 #define DOR_FLOPPY_MOTOR_ON_A 0x10 78 #define DOR_FLOPPY_MOTOR_ON_B 0x20 79 #define DOR_FLOPPY_MOTOR_ON_C 0x40 /* Reserved on PS/2 */ 80 #define DOR_FLOPPY_MOTOR_ON_D 0x80 /* Reserved on PS/2 */ 81 82 /* DOR_FLOPPY_DRIVE_SELECT */ 83 #define DOR_FLOPPY_DRIVE_SELECT_A 0x0 84 #define DOR_FLOPPY_DRIVE_SELECT_B 0x1 85 #define DOR_FLOPPY_DRIVE_SELECT_C 0x2 /* Reserved on PS/2 */ 86 #define DOR_FLOPPY_DRIVE_SELECT_D 0x3 /* Reserved on PS/2 */ 87 88 /* MAIN_STATUS_REGISTER */ 89 #define MSR_FLOPPY_BUSY_0 0x1 90 #define MSR_FLOPPY_BUSY_1 0x2 91 #define MSR_FLOPPY_BUSY_2 0x4 /* Reserved on PS/2 */ 92 #define MSR_FLOPPY_BUSY_3 0x8 /* Reserved on PS/2 */ 93 #define MSR_READ_WRITE_IN_PROGRESS 0x10 94 #define MSR_NON_DMA_MODE 0x20 95 #define MSR_IO_DIRECTION 0x40 /* Determines meaning of Command Status Registers */ 96 #define MSR_DATA_REG_READY_FOR_IO 0x80 97 98 /* DATA_RATE_SELECT_REGISTER */ 99 #define DRSR_DSEL 0x3 /* covers two bits as defined below */ 100 #define DRSR_PRECOMP 0x1c /* covers three bits as defined below */ 101 #define DRSR_MBZ 0x20 102 #define DRSR_POWER_DOWN 0x40 103 #define DRSR_SW_RESET 0x80 104 105 /* DRSR_DSEL */ 106 #define DRSR_DSEL_500KBPS 0x0 107 #define DRSR_DSEL_300KBPS 0x1 108 #define DRSR_DSEL_250KBPS 0x2 109 #define DRSR_DSEL_1MBPS 0x3 110 111 /* STATUS_REGISTER_0 */ 112 #define SR0_UNIT_SELECTED_AT_INTERRUPT 0x3 /* Covers two bits as defined below */ 113 #define SR0_HEAD_NUMBER_AT_INTERRUPT 0x4 /* Values defined below */ 114 #define SR0_NOT_READY_ON_READ_WRITE 0x8 /* Unused in PS/2 */ 115 #define SR0_SS_ACCESS_TO_HEAD_1 0x8 /* Unused in PS/2 */ 116 #define SR0_EQUIPMENT_CHECK 0x10 117 #define SR0_SEEK_COMPLETE 0x20 118 #define SR0_LAST_COMMAND_STATUS 0xC0 /* Covers two bits as defined below */ 119 120 /* SR0_UNIT_SELECTED_AT_INTERRUPT */ 121 #define SR0_UNIT_SELECTED_A 0x0 122 #define SR0_UNIT_SELECTED_B 0x1 123 #define SR0_UNIT_SELECTED_C 0x2 124 #define SR0_UNIT_SELECTED_D 0x3 125 #define SR0_PS2_UNIT_SELECTED_A 0x1 /* PS/2 uses only two drives: A = 01b B = 10b */ 126 #define SR0_PST_UNIT_SELECTED_B 0x2 127 128 /* SR0_HEAD_NUMBER_AT_INTERRUPT */ 129 #define SR0_HEAD_0 0x0 130 #define SR0_HEAD_1 0x1 131 132 /* SR0_LAST_COMMAND_STATUS */ 133 #define SR0_LCS_SUCCESS 0x0 134 #define SR0_LCS_TERMINATED_ABNORMALLY 0x40 135 #define SR0_LCS_INVALID_COMMAND_ISSUED 0x80 136 #define SR0_LCS_READY_SIGNAL_CHANGED 0xc0 /* Reserved on PS/2; a/k/a abnormal termination due to polling */ 137 138 /* STATUS_REGISTER_1 */ 139 #define SR1_CANNOT_FIND_ID_ADDRESS 0x1 /* Mimics SR2_WRONG_CYLINDER_DETECTED */ 140 #define SR1_WRITE_PROTECT_DETECTED 0x2 141 #define SR1_CANNOT_FIND_SECTOR_ID 0x4 142 #define SR1_OVERRUN 0x10 143 #define SR1_CRC_ERROR 0x20 144 #define SR1_END_OF_CYLINDER 0x80 145 146 /* STATUS_REGISTER_2 */ 147 #define SR2_MISSING_ADDRESS_MARK 0x1 148 #define SR2_BAD_CYLINDER 0x2 149 #define SR2_SCAN_COMMAND_FAILED 0x4 150 #define SR2_SCAN_COMMAND_EQUAL 0x8 151 #define SR2_WRONG_CYLINDER_DETECTED 0x10 /* Mimics SR1_CANNOT_FIND_ID_ADDRESS */ 152 #define SR2_CRC_ERROR_IN_SECTOR_DATA 0x20 153 #define SR2_SECTOR_WITH_DELETED_DATA 0x40 154 155 /* STATUS_REGISTER_3 */ 156 #define SR3_UNIT_SELECTED 0x3 /* Covers two bits; defined below */ 157 #define SR3_SIDE_HEAD_SELECT_STATUS 0x4 /* Values defined below */ 158 #define SR3_TWO_SIDED_STATUS_SIGNAL 0x8 159 #define SR3_TRACK_ZERO_STATUS_SIGNAL 0x10 160 #define SR3_READY_STATUS_SIGNAL 0x20 161 #define SR3_WRITE_PROTECT_STATUS_SIGNAL 0x40 162 #define SR3_FAULT_STATUS_SIGNAL 0x80 163 164 /* SR3_UNIT_SELECTED */ 165 #define SR3_UNIT_SELECTED_A 0x0 166 #define SR3_UNIT_SELECTED_B 0x1 167 #define SR3_UNIT_SELECTED_C 0x2 168 #define SR3_UNIT_SELECTED_D 0x3 169 170 /* SR3_SIDE_HEAD_SELECT_STATUS */ 171 #define SR3_SHSS_HEAD_0 0x0 172 #define SR3_SHSS_HEAD_1 0x1 173 174 /* DIGITAL_INPUT_REGISTER */ 175 #define DIR_HIGH_DENSITY_SELECT 0x1 176 #define DIR_DISKETTE_CHANGE 0x80 177 178 /* CONFIGURATION_CONTROL_REGISTER */ 179 #define CCR_DRC 0x3 /* Covers two bits, defined below */ 180 #define CCR_DRC_0 0x1 181 #define CCR_DRC_1 0x2 182 183 /* CCR_DRC */ 184 #define CCR_DRC_500000 0x0 185 #define CCR_DRC_250000 0x2 186 187 /* Commands */ 188 #define COMMAND_READ_TRACK 0x2 189 #define COMMAND_SPECIFY 0x3 190 #define COMMAND_SENSE_DRIVE_STATUS 0x4 191 #define COMMAND_WRITE_DATA 0x5 192 #define COMMAND_READ_DATA 0x6 193 #define COMMAND_RECALIBRATE 0x7 194 #define COMMAND_SENSE_INTERRUPT_STATUS 0x8 195 #define COMMAND_WRITE_DELETED_DATA 0x9 196 #define COMMAND_READ_ID 0xA 197 #define COMMAND_READ_DELETED_DATA 0xC 198 #define COMMAND_FORMAT_TRACK 0xD 199 #define COMMAND_SEEK 0xF 200 #define COMMAND_VERSION 0x10 201 #define COMMAND_SCAN_EQUAL 0x11 202 #define COMMAND_CONFIGURE 0x13 203 #define COMMAND_SCAN_LOW_OR_EQUAL 0x19 204 #define COMMAND_SCAN_HIGH_OR_EQUAL 0x1D 205 206 /* COMMAND_READ_DATA constants */ 207 #define READ_DATA_DS0 0x1 208 #define READ_DATA_DS1 0x2 209 #define READ_DATA_HDS 0x4 210 #define READ_DATA_SK 0x20 211 #define READ_DATA_MFM 0x40 212 #define READ_DATA_MT 0x80 213 214 /* COMMAND_READ_ID constants */ 215 #define READ_ID_MFM 0x40 216 217 /* COMMAND_SPECIFY constants */ 218 #define SPECIFY_HLT_1M 0x10 /* 16ms; based on intel data sheet */ 219 #define SPECIFY_HLT_500K 0x8 /* 16ms; based on intel data sheet */ 220 #define SPECIFY_HLT_300K 0x6 /* 16ms; based on intel data sheet */ 221 #define SPECIFY_HLT_250K 0x4 /* 16ms; based on intel data sheet */ 222 #define SPECIFY_HUT_1M 0x0 /* Need to figure out these eight values; 0 is max */ 223 #define SPECIFY_HUT_500K 0x0 224 #define SPECIFY_HUT_300K 0x0 225 #define SPECIFY_HUT_250K 0x0 226 #define SPECIFY_SRT_1M 0x0 227 #define SPECIFY_SRT_500K 0x0 228 #define SPECIFY_SRT_300K 0x0 229 #define SPECIFY_SRT_250K 0x0 230 231 /* Command byte 1 constants */ 232 #define COMMAND_UNIT_SELECT 0x3 /* Covers two bits; defined below */ 233 #define COMMAND_UNIT_SELECT_0 0x1 234 #define COMMAND_UNIT_SELECT_1 0x2 235 #define COMMAND_HEAD_NUMBER 0x4 236 #define COMMAND_HEAD_NUMBER_SHIFT 0x2 237 238 /* COMMAND_VERSION */ 239 #define VERSION_ENHANCED 0x90 240 241 /* COMMAND_UNIT_SELECT */ 242 #define CUS_UNIT_0 0x0 243 #define CUS_UNIT_1 0x1 244 245 /* COMMAND_CONFIGURE constants */ 246 #define CONFIGURE_FIFOTHR 0xf 247 #define CONFIGURE_POLL 0x10 248 #define CONFIGURE_EFIFO 0x20 249 #define CONFIGURE_EIS 0x40 250 #define CONFIGURE_PRETRK 0xff 251 252 /* Command Head Number Constants */ 253 #define COMMAND_HEAD_0 0x0 254 #define COMMAND_HEAD_1 0x1 255 256 /* Bytes per sector constants */ 257 #define HW_128_BYTES_PER_SECTOR 0x0 258 #define HW_256_BYTES_PER_SECTOR 0x1 259 #define HW_512_BYTES_PER_SECTOR 0x2 260 #define HW_1024_BYTES_PER_SECTOR 0x3 261 262 /* 263 * FUNCTIONS 264 */ 265 NTSTATUS NTAPI 266 HwTurnOnMotor(PDRIVE_INFO DriveInfo); 267 268 NTSTATUS NTAPI 269 HwSenseDriveStatus(PDRIVE_INFO DriveInfo); 270 271 NTSTATUS NTAPI 272 HwReadWriteData(PCONTROLLER_INFO ControllerInfo, 273 BOOLEAN Read, 274 UCHAR Unit, 275 UCHAR Cylinder, 276 UCHAR Head, 277 UCHAR Sector, 278 UCHAR BytesPerSector, 279 UCHAR EndOfTrack, 280 UCHAR Gap3Length, 281 UCHAR DataLength); 282 283 NTSTATUS NTAPI 284 HwRecalibrate(PDRIVE_INFO DriveInfo); 285 286 NTSTATUS NTAPI 287 HwSenseInterruptStatus(PCONTROLLER_INFO ControllerInfo); 288 289 NTSTATUS NTAPI 290 HwReadId(PDRIVE_INFO DriveInfo, UCHAR Head); 291 292 NTSTATUS NTAPI 293 HwFormatTrack(PCONTROLLER_INFO ControllerInfo, 294 UCHAR Unit, 295 UCHAR Head, 296 UCHAR BytesPerSector, 297 UCHAR SectorsPerTrack, 298 UCHAR Gap3Length, 299 UCHAR FillerPattern); 300 301 NTSTATUS NTAPI 302 HwSeek(PDRIVE_INFO DriveInfo, UCHAR Cylinder); 303 304 NTSTATUS NTAPI 305 HwReadWriteResult(PCONTROLLER_INFO ControllerInfo); 306 307 NTSTATUS NTAPI 308 HwGetVersion(PCONTROLLER_INFO ControllerInfo); 309 310 NTSTATUS NTAPI 311 HwConfigure(PCONTROLLER_INFO ControllerInfo, 312 BOOLEAN EIS, 313 BOOLEAN EFIFO, 314 BOOLEAN POLL, 315 UCHAR FIFOTHR, 316 UCHAR PRETRK) ; 317 318 NTSTATUS NTAPI 319 HwRecalibrateResult(PCONTROLLER_INFO ControllerInfo); 320 321 NTSTATUS NTAPI 322 HwDiskChanged(PDRIVE_INFO DriveInfo, 323 PBOOLEAN DiskChanged); 324 325 NTSTATUS NTAPI 326 HwSenseDriveStatusResult(PCONTROLLER_INFO ControllerInfo, 327 PUCHAR Status); 328 329 NTSTATUS NTAPI 330 HwSpecify(PCONTROLLER_INFO ControllerInfo, 331 UCHAR HeadLoadTime, 332 UCHAR HeadUnloadTime, 333 UCHAR StepRateTime, 334 BOOLEAN NonDma); 335 336 NTSTATUS NTAPI 337 HwReadIdResult(PCONTROLLER_INFO ControllerInfo, 338 PUCHAR CurCylinder, 339 PUCHAR CurHead); 340 341 NTSTATUS NTAPI 342 HwSetDataRate(PCONTROLLER_INFO ControllerInfo, UCHAR DataRate); 343 344 NTSTATUS NTAPI 345 HwReset(PCONTROLLER_INFO Controller); 346 347 NTSTATUS NTAPI 348 HwPowerOff(PCONTROLLER_INFO ControllerInfo); 349 350 VOID NTAPI 351 HwDumpRegisters(PCONTROLLER_INFO ControllerInfo); 352 353 NTSTATUS NTAPI 354 HwTurnOffMotor(PCONTROLLER_INFO ControllerInfo); 355