     1                                  ;***
     2                                  ;	Title:	Disk
     3                                  ;	C:	(C) Copyright 1988 by Microsoft corp.
     4                                  ;	Date:	1/11/85
     5                                  ;
     6                                  ;		There is a bug in some versions of IBM's AT ROM BIOS.
     7                                  ;		Interrupts are not disabled during read operations.
     8                                  ;
     9                                  ;	Use:	This program should be chained in line with the disk
    10                                  ;		interupt 13h, it intercepts read calls to the hard disk
    11                                  ;		and handles them appropriately.  For other functions it
    12                                  ;		passes controll to OLD13, which should contain the
    13                                  ;		address of the AT ROM disk routine. The entry point for
    14                                  ;		this program is IBM_DISK_IO.
    15                                  ;
    16                                  
    17                                  
    18                                  	cpu 286		;Use 80286 non-protected mode
    19                                  	assume nocheck, ds:BIOSDATA
    20                                  
    21                                  BIOSEG		equ 040h		;Segment for ROM BIOS Data
    22                                  ROMSEG		equ 0F000h	;Segment of ROM
    23                                  
    24                                  %idefine ORG absolute	; just address things without segment
    25                                  
    26                                  ; === alternative section BIOSDATA
    27                                  
    28                                  BAD_DISK 	equ 01
    29                                  
    30                                  HF_PORT 	equ 01F0h
    31                                  HF_REG_PORT 	equ 03F6h
    32                                  
    33                                  ;*	Offsets into Fixed disk parameter table
    34                                  FDP_PRECOMP	equ 5
    35                                  FDP_CONTROL 	equ 8
    36                                  
    37                                  ;section DATA	;ROM BIOS data segment
    38                                  %if 0
    39                                  section DATA	; NASM port directive for fixmem.pl
    40                                  %endif
    41                                  
    42                                  	ORG 42h
    43 00000042 ????????????            CMD_BLOCK	DB 6 DUP (?)
    44                                  
    45                                  ;*	Offsets into CMD_BLOCK for registers
    46                                  PRE_COMP equ 0	;Write Pre-compensation
    47                                  SEC_CNT	 equ 1	;Sector count
    48                                  SEC_NUM	 equ 2	;Sector number
    49                                  CYL_LOW	 equ 3	;Cylinder number, low part
    50                                  CYL_HIGH equ 4	;Cylinder number, high part
    51                                  DRV_HEAD equ 5	;Drive/Head (Bit 7 = ECC mode, Bit 5 = 512 byte sectors, 
    52                                  		;            Bit 4 = drive number, Bits 3-0 have head number)
    53                                  CMD_REG  equ 6	;Command register
    54                                  
    55                                  
    56                                  	ORG 074h
    57                                  
    58 00000074 ??                      DISK_STATUS1 	DB ?
    59 00000075 ??                      HF_NUM		DB ?
    60 00000076 ??                      CONTROL_BYTE	DB ?
    61                                  
    62                                  ; (no prior section) ; DATA	ENDS
    63                                  
    64                                  ; === no alternative section
    65                                  
    66                                  
    67                                  ;***	Define where the ROM routines are actually located
    68                                  ;section ROM
    69                                  
    70                                  	ORG 02E1Eh
    71                                  ROMCOMMAND PROC FAR
    72                                  ROMCOMMAND ENDP
    73                                  
    74                                  	ORG 02E7Fh
    75                                  ROMWAIT	PROC FAR
    76                                  ROMWAIT	ENDP
    77                                  
    78                                  	ORG 02EE2h
    79                                  ROMWAIT_DRQ PROC FAR
    80                                  ROMWAIT_DRQ ENDP
    81                                  
    82                                  	ORG 02EF8h
    83                                  ROMCHECK_STATUS PROC FAR
    84                                  ROMCHECK_STATUS ENDP
    85                                  
    86                                  	ORG 02F69h
    87                                  ROMCHECK_DMA PROC FAR
    88                                  ROMCHECK_DMA ENDP
    89                                  
    90                                  	ORG 02F8Eh
    91                                  ROMGET_VEC PROC FAR
    92                                  ROMGET_VEC ENDP
    93                                  
    94                                  	ORG 0FF65h
    95                                  ROMFRET PROC FAR	;Far return at F000:FF65 in AT ROM.
    96                                  ROMFRET ENDP
    97                                  
    98                                  ; (no prior section) ; ROM	ENDS
    99                                  
   100                                  %define MSHARD
   101                                  %include "entryseg.nas"
     1                              <1> 
     2                              <1> %ifndef ENTRYSEGNAS
     3                              <1> %define ENTRYSEGNAS 1
     4                              <1> 
     5                              <1> %include "lmacros3.mac"
     1                              <2> [list -]
     1          ******************  <2>  warning: redefining multi-line macro `struc' [-w+pp-macro-redef-multi]
    14                              <3> [list -]
    14                              <2> [list -]
     6                              <1> %include "entrysw.mac"
     1                              <2> 
     2                              <2> %ifndef __ENTRYSW_MAC__
     3                              <2>  %assign __ENTRYSW_MAC__ 1
     4                              <2> 
     5                              <2> %assign _DOSCODEHMA		1
     6                              <2> %assign _RELOCATEDOSCODE	0
     7                              <2> 
     8                              <2> 		; Write a label "%1" (only if DOSCODE isn't relocated) and
     9                              <2> 		; "relocated%1" (always).
    10                              <2> 	%imacro relocated 1-2.nolist
    11                              <2> %ifnidni %2, device
    12                              <2>  %ifnidni %2, amis
    13                              <2>   %ifn _RELOCATEDOSCODE
    14                              <2> %1:
    15                              <2> 	global %1
    16                              <2>   %endif
    17                              <2>  %endif
    18                              <2> %endif
    19                              <2> relocated%1:				; always used for local labels
    20                              <2> 	global relocated%1
    21                              <2> 	%endmacro
    22                              <2> 
    23                              <2> %if _RELOCATEDOSCODE
    24                              <2> DOSENTRYADJUSTSEGMENT equ 60h - 26h
    25                              <2> %else
    26                              <2> DOSENTRYADJUSTSEGMENT equ 0
    27                              <2> %endif
    28                              <2> DOSENTRYADJUSTOFFSET equ DOSENTRYADJUSTSEGMENT * 16
    29                              <2> 
    30                              <2> DOSENTRYDEVICEBASE equ 10h
    31                              <2> 
    32                              <2> %endif
     7                              <1> [list -]
    23                              <1>  %define DOSENTRYGROUP DOSCODEGROUP
    24                              <1>  [list -]
    39                              <1> usesection DOSENTRY
    40                              <1> 
    41                              <1> %endif
   102                                  
   103                                  usesection DOSENTRYHARD
   104                                  
   105                                   global DOSENTRY_INIT_START
   106                                  DOSENTRY_INIT_START:
   107                                  
   108                                  EXTRN	OLD13:DWORD		;Link to AT bios int 13h
   109                                  
   110                                  PUBLIC	IBM_DISK_IO	
   111                                  
   112                                  
   113                                  ;***	IBM_DISK_IO - main routine, fixes AT ROM bug
   114                                  ;
   115                                  ;	ENTRY:	(AH) = function, 02 or 0A for read.
   116                                  ;		(DL) = drive number (80h or 81h).
   117                                  ;		(DH) = head number.
   118                                  ;		(CH) = cylinder number.
   119                                  ;		(CL) = Sector number (high 2 bits has cylinder number).
   120                                  ;		(AL) = number of sectors.
   121                                  ;		(ES:BX) = address of read buffer.
   122                                  ;		For more on register contents see ROM BIOS listing.
   123                                  ;		Stack set up for return by an IRET.
   124                                  ;
   125                                  ;	EXIT:	(AH) = status of current operation.
   126                                  ;		(CY) = 1 IF failed, 0 if successful.
   127                                  ;		For other register contents see ROM BIOS listing.
   128                                  ;
   129                                  ;	USES:	
   130                                  ;
   131                                  ;
   132                                  ;	WARNING: Uses OLD13 vector for non-read calls.
   133                                  ;		Does direct calls to the AT ROM.
   134                                  ;		Does segment arithmatic.
   135                                  ;
   136                                  ;	EFFECTS: Performs DISK I/O operation.
   137                                  ;
   138                                  IBM_DISK_IO PROC FAR
   139 00000000 80FA80                  	CMP DL, 80h
   140 00000003 720A                    	JB  ATD1		;Pass through floppy disk calls.
   141 00000005 80FC02                  	CMP AH, 02
   142 00000008 740A                    	JE  ATD2		;Intercept call 02 (read sectors).
   143 0000000A 80FC0A                  	CMP AH, 0Ah
   144 0000000D 7405                    	JE  ATD2		;and call 0Ah (read long).
   145                                  ATD1:
   146 0000000F 2EFF2E[0000]            	JMP far [cs:OLD13]		;Use ROM INT 13h handler.
   147                                  ATD2:
   148 00000014 53                      	PUSH BX
   149 00000015 51                      	PUSH CX
   150 00000016 52                      	PUSH DX
   151 00000017 57                      	PUSH DI
   152 00000018 1E                      	PUSH DS
   153 00000019 06                      	PUSH ES
   154 0000001A 50                      	PUSH AX
   155 0000001B B84000                  	MOV  AX,BIOSEG		;Establish BIOS segment addressing.
   156 0000001E 8ED8                    	MOV  DS,AX
   157                                   assume nocheck, ds:BIOSDATA
   158 00000020 C606740000              	MOV  byte [DISK_STATUS1], 0	;Initially no error code.
   159 00000025 80E27F                  	AND  DL, 07fh		;Mask to hard disk number
   160 00000028 3A167500                	CMP  DL, [HF_NUM]
   161 0000002C 7207                    	JB   ATD3		;Disk number in range
   162 0000002E C606740001              	MOV  byte [DISK_STATUS1], BAD_DISK
   163 00000033 EB20                    	JMP  SHORT ATD4		;Disk number out of range error, return
   164                                  
   165                                  ATD3:
   166 00000035 53                      	PUSH BX
   167 00000036 8CC0                    	MOV  AX, ES		;Make ES:BX to Seg:000x form.
   168 00000038 C1EB04                  	SHR  BX, 4
   169 0000003B 01D8                    	ADD  AX, BX
   170 0000003D 8EC0                    	MOV  ES, AX
   171                                   assume nocheck, es:nothing
   172 0000003F 5B                      	POP  BX
   173 00000040 83E30F                  	AND  BX,000Fh
   174 00000043 0E                      	PUSH CS
   175 00000044 E8DE00                  	CALL CHECK_DMA
   176 00000047 720C                    	JC   ATD4		;Abort if DMA across segment boundary
   177                                  
   178 00000049 58                      	POP  AX			;Restore AX register for SETCMD
   179 0000004A 50                      	PUSH AX
   180 0000004B E81A00                  	CALL SETCMD		;Set up command block for disk op
   181 0000004E BAF603                  	MOV  DX, HF_REG_PORT
   182 00000051 EE                      	OUT  DX, AL		;Write out command modifier
   183 00000052 E86B00                  	CALL DOCMD		;Carry out command
   184                                  ATD4:
   185                                  ;;  Old code - Carry cleared after set by logical or opearation
   186                                  ;;	POP  AX
   187                                  ;;	MOV  AH,DISK_STATUS1	;On return AH has error code
   188                                  ;;	STC
   189                                  ;;	OR   AH,AH
   190                                  ;;	JNZ  ATD5 		;Carry set if error
   191                                  ;;	CLC
   192                                  ;;---------------------------------------------------
   193                                  ;;  New Code - Let Logical or clear carry and then set carry if ah!=0
   194                                  ;;             And save a couple bytes while were at it.
   195 00000055 58                      	POP  AX
   196 00000056 8A267400                	MOV  AH,[DISK_STATUS1]	;On return AH has error code
   197 0000005A 08E4                    	OR   AH,AH
   198 0000005C 7401                    	JZ   ATD5 		;Carry set if error
   199 0000005E F9                      	STC
   200                                  
   201                                  ATD5:
   202 0000005F 07                      	POP  ES
   203 00000060 1F                      	POP  DS
   204                                   assume nocheck, ds:nothing, es:nothing
   205 00000061 5F                      	POP  DI
   206 00000062 5A                      	POP  DX
   207 00000063 59                      	POP  CX
   208 00000064 5B                      	POP  BX
   209 00000065 CA0200                  	RET  2			;Far return, dropping flags
   210                                  IBM_DISK_IO ENDP
   211                                  
   212                                  
   213                                  
   214                                  ;***	SETCMD - Set up CMD_BLOCK for the disk operation
   215                                  ;
   216                                  ;	ENTRY:	(DS) = BIOS Data segment.
   217                                  ;		(ES:BX) in seg:000x form.
   218                                  ;		Other registers as in INT 13h call
   219                                  ;	
   220                                  ;	EXIT:	CMD_BLOCK set up for disk read call.
   221                                  ;		CONTROL_BYTE set up for disk operation.
   222                                  ;		(AL) = Control byte modifier
   223                                  ;
   224                                  ;
   225                                  ;	Sets the fields of CMD_BLOCK using the register contents
   226                                  ;	and the contents of the disk parameter block for the given drive.
   227                                  ;
   228                                  ;	WARNING: (AX) destroyed.
   229                                  ;		Does direct calls to the AT ROM.
   230                                  ;
   231                                  SETCMD	PROC NEAR
   232                                   assume nocheck, ds:BIOSDATA
   233 00000068 A24300                  	MOV  [CMD_BLOCK + SEC_CNT], AL
   234 0000006B C606480020              	MOV  byte [CMD_BLOCK + CMD_REG], 020h	;Assume function 02
   235 00000070 80FC02                  	CMP  AH, 2
   236 00000073 7405                    	JE   SETC1			;CMD_REG = 20h if function 02 (read)
   237 00000075 C606480022              	MOV  byte [CMD_BLOCK + CMD_REG], 022h   ;CMD_REG = 22h if function 0A (" long)
   238                                  SETC1:					;No longer need value in AX
   239 0000007A 88C8                    	MOV  AL, CL
   240 0000007C 243F                    	AND  AL, 03fh			;Mask to sector number
   241 0000007E A24400                  	MOV  [CMD_BLOCK + SEC_NUM], AL
   242 00000081 882E4500                	MOV  [CMD_BLOCK + CYL_LOW], CH
   243 00000085 88C8                    	MOV  AL, CL
   244 00000087 C0E806                  	SHR  AL, 6			;Get two high bits of cylender number
   245 0000008A A24600                  	MOV  [CMD_BLOCK + CYL_HIGH], AL
   246 0000008D 89D0                    	MOV  AX, DX
   247 0000008F C0E004                  	SHL  AL, 4			;Drive number
   248 00000092 80E40F                  	AND  AH, 0Fh
   249 00000095 08E0                    	OR   AL, AH			;Head number
   250 00000097 0CA0                    	OR   AL, 0A0h			;Set ECC and 512 bytes per sector
   251 00000099 A24700                  	MOV  [CMD_BLOCK + DRV_HEAD], AL
   252 0000009C 06                      	PUSH ES				;GET_VEC destroys ES:BX
   253 0000009D 53                      	PUSH BX
   254 0000009E 0E                      	PUSH CS
   255 0000009F E85B00                  	CALL GET_VEC
   256 000000A2 268B4705                	MOV  AX, [ES:FDP_PRECOMP + BX]	;Write pre-comp from disk parameters
   257 000000A6 C1E802                  	SHR  AX, 2
   258 000000A9 A24200                  	MOV  [CMD_BLOCK + PRE_COMP],AL	;Only use low part
   259 000000AC 268A4708                	MOV  AL, [ES:FDP_CONTROL + BX]	;Control byte modifier
   260 000000B0 5B                      	POP  BX
   261 000000B1 07                      	POP  ES
   262                                   assume nocheck, es:nothing
   263 000000B2 8A267600                	MOV  AH, [CONTROL_BYTE]
   264 000000B6 80E4C0                  	AND  AH, 0C0h			;Keep disable retry bits
   265 000000B9 08C4                    	OR   AH, AL
   266 000000BB 88267600                	MOV  [CONTROL_BYTE], AH
   267 000000BF C3                      	RET
   268                                  SETCMD	ENDP	
   269                                  
   270                                  
   271                                  
   272                                  ;***	DOCMD - Carry out READ operation to AT hard disk
   273                                  ;
   274                                  ;	ENTRY:	(ES:BX) = address for read in data.
   275                                  ;		CMD_BLOCK set up for disk read.
   276                                  ;
   277                                  ;	EXIT:	Buffer at (ES:BX) contains data read.
   278                                  ;		DISK_STATUS1 set to error code (0 if success).
   279                                  ;
   280                                  ;	
   281                                  ;
   282                                  ;	WARNING: (AX), (BL), (CX), (DX), (DI) destroyed.
   283                                  ;		No check is made for DMA boundary overrun.
   284                                  ;
   285                                  ;	EFFECTS: Programs disk controller.
   286                                  ;		Performs disk input.
   287                                  ;
   288                                  DOCMD	PROC NEAR
   289 000000C0 89DF                    	MOV  DI, BX		;(ES:DI) = data buffer addr.
   290 000000C2 0E                      	PUSH CS
   291 000000C3 E83F00                  	CALL mshard_COMMAND
   292 000000C6 7534                    	JNZ  DOC3
   293                                  DOC1:
   294 000000C8 0E                      	PUSH CS
   295 000000C9 E84100                  	CALL WAITT		;Wait for controller to complete read
   296 000000CC 752E                    	JNZ  DOC3
   297 000000CE B90001                  	MOV  CX, 100h		;256 words per sector
   298 000000D1 BAF001                  	MOV  DX, HF_PORT
   299 000000D4 FC                      	CLD			;String op goes up
   300 000000D5 FA                      	CLI			;Disable interrupts (BUG WAS FORGETTING THIS)
   301 000000D6 F36D                      REPZ  INSW			;Read in sector
   302 000000D8 FB                        	STI
   303 000000D9 F606480002              	TEST byte [CMD_BLOCK + CMD_REG], 02
   304 000000DE 7410                    	JZ   DOC2		;No ECC bytes to read.
   305 000000E0 0E                      	PUSH CS
   306 000000E1 E83100                  	CALL WAIT_DRQ
   307 000000E4 7216                    	JC   DOC3
   308 000000E6 B90400                  	MOV  CX, 4		;4 bytes of ECC
   309 000000E9 BAF001                  	MOV  DX, HF_PORT
   310 000000EC FA                      	CLI
   311 000000ED F36C                      REPZ  INSB			;Read in ECC
   312 000000EF FB                        	STI
   313                                  DOC2:
   314 000000F0 0E                      	PUSH CS
   315 000000F1 E82900                  	CALL CHECK_STATUS
   316 000000F4 7506                    	JNZ  DOC3		;Operation failed
   317 000000F6 FE0E4300                	DEC  byte [CMD_BLOCK + SEC_CNT]	
   318 000000FA 75CC                    	JNZ  DOC1		;Loop while more sectors to read
   319                                  DOC3:
   320 000000FC C3                      	RET
   321                                  DOCMD	ENDP
   322                                  
   323                                  
   324                                  
   325                                  ;***	GET_VEC - Get pointer to hard disk parameters.
   326                                  ;
   327                                  ;	ENTRY:	(DL) = Low bit has hard disk number (0 or 1).
   328                                  ;
   329                                  ;	EXIT:	(ES:BX) = address of disk parameters table.
   330                                  ;
   331                                  ;	USES:	AX for segment computation.
   332                                  ;
   333                                  ;	Loads ES:BX from interrupt table in low memory, vector 46h (disk 0)
   334                                  ;	or 70h (disk 1).
   335                                  ;	
   336                                  ;	WARNING: (AX) destroyed.
   337                                  ;		This does a direct call to the AT ROM.
   338                                  ;
   339                                  GET_VEC	PROC NEAR
   340 000000FD 6865FF                  	PUSH OFFSET ROMFRET
   341 00000100 EA8E2F00F0              	JMP  ROMSEG:ROMGET_VEC
   342                                  GET_VEC ENDP
   343                                  
   344                                  
   345                                  
   346                                  ;***	COMMAND - Send contents of CMD_BLOCK to disk controller.
   347                                  ;
   348                                  ;	ENTRY:	Control_byte 
   349                                  ;		CMD_BLOCK - set up with values for hard disk controller.
   350                                  ;
   351                                  ;	EXIT:	DISK_STATUS1 = Error code.
   352                                  ;		NZ if error, ZR for no error.
   353                                  ;
   354                                  ;
   355                                  ;	WARNING: (AX), (CX), (DX) destroyed.
   356                                  ;		Does a direct call to the AT ROM.
   357                                  ;
   358                                  ;	EFFECTS: Programs disk controller.
   359                                  ;
   360                                  mshard_COMMAND	PROC NEAR
   361 00000105 6865FF                  	PUSH OFFSET ROMFRET
   362 00000108 EA1E2E00F0              	JMP  ROMSEG:ROMCOMMAND
   363                                  mshard_COMMAND ENDP
   364                                  
   365                                  
   366                                  
   367                                  ;***	WAITT - Wait for disk interrupt
   368                                  ;
   369                                  ;	ENTRY:	Nothing.
   370                                  ;
   371                                  ;	EXIT:	DISK_STATUS1 = Error code.
   372                                  ;		NZ if error, ZR if no error.
   373                                  ;
   374                                  ;
   375                                  ;	WARNING: (AX), (BL), (CX) destroyed.
   376                                  ;		Does a direct call to the AT ROM.
   377                                  ;		
   378                                  ;	EFFECTS: Calls int 15h, function 9000h.
   379                                  ;
   380                                  WAITT	PROC NEAR
   381 0000010D 6865FF                  	PUSH OFFSET ROMFRET 
   382 00000110 EA7F2E00F0              	JMP  ROMSEG:ROMWAIT
   383                                  WAITT	ENDP
   384                                  
   385                                  
   386                                  
   387                                  ;***	WAIT_DRQ - Wait for data request.
   388                                  ;
   389                                  ;	ENTRY:	Nothing.
   390                                  ;
   391                                  ;	EXIT:	DISK_STATUS1 = Error code.
   392                                  ;		CY if error, NC if no error.
   393                                  ;
   394                                  ;
   395                                  ;	WARNING: (AL), (CX), (DX) destroyed.
   396                                  ;		Does a direct call to the AT ROM.
   397                                  ;
   398                                  WAIT_DRQ PROC NEAR
   399 00000115 6865FF                  	PUSH OFFSET ROMFRET
   400 00000118 EAE22E00F0              	JMP  ROMSEG:ROMWAIT_DRQ
   401                                  WAIT_DRQ ENDP
   402                                  
   403                                  
   404                                  
   405                                  ;***	CHECK_STATUS - Check hard disk status.
   406                                  ;
   407                                  ;	ENTRY:	Nothing.
   408                                  ;
   409                                  ;	EXIT:	DISK_STATUS1 = Error code.
   410                                  ;		NZ if error, ZR if no error.
   411                                  ;
   412                                  ;
   413                                  ;	WARNING: (AX), (CX), (DX) destroyed.
   414                                  ;		Does a direct call to the AT ROM.
   415                                  ;
   416                                  CHECK_STATUS PROC NEAR
   417 0000011D 6865FF                  	PUSH OFFSET ROMFRET
   418 00000120 EAF82E00F0              	JMP  ROMSEG:ROMCHECK_STATUS
   419                                  CHECK_STATUS ENDP
   420                                  
   421                                  
   422                                  
   423                                  ;***	CHECK_DMA - check for DMA overrun 64k segment.
   424                                  ;
   425                                  ;	ENTRY:	(ES:BX) = addr. of memory buffer in seg:000x form.
   426                                  ;		CMD_BLOCK set up for operation.
   427                                  ;
   428                                  ;	EXIT:	DISK_STATUS1 - Error code.
   429                                  ;		CY if error, NC if no error.
   430                                  ;
   431                                  ;
   432                                  ;	WARNING: Does a direct call to the AT ROM.
   433                                  ;
   434                                  CHECK_DMA PROC NEAR
   435 00000125 6865FF                  	PUSH OFFSET ROMFRET
   436 00000128 EA692F00F0              	JMP  ROMSEG:ROMCHECK_DMA
   437                                  CHECK_DMA ENDP
   438                                  
   439                                  
   440                                  ; (no prior section) ; CODE	ENDS
   441                                  	END
