ORG 00H
	; Ports for normal IDE/ATA are
	; 0x001F0 Primary 	Irq 14
	; 0x00170 Secondary	Irq 15
	; 0x001E8 Tertiary	Irq 11
	; 0x00168 Quaternary	Irq 10
	; 0x0D800 PCI-IDE 	Irq 9 - Please note that the IRQ on dual
	; 0x0E400 PCI-IDE 	Irq 9 - channel PCI-IDE cards is shared per
	;                             - chip not per channel

;BASEOFPORT	EQU	0E400H
BASEOFPORT	EQU	0168H
;BASEOFPORT	EQU	0170H
;BASEOFPORT	EQU	01F0H

	; Secondary status register at Base+0x206 not used
	; because register not present on many ISA add-in
	; cards and not at that address on PCI cards at all in native mode.
	
	; We don't use IRQ's yet so they are irrelavent for now.
	
	; For the meaning of the remainder of the ID block
	; sent by devices in responce to the command please goto
	; http://www.t13.org and look up ATA/ATAPI 3 or later.
	
        ; Bios Segment is 040h
        ; Variable 40:75 In Hex is HD count
	
	; XFERSEG : Transfer Segment
	; XFEROFS : Transfer Offset
	; XFERCNT : Transfer Count
	
	; CHS format of registers is as follows
	; DL = Drive Number
	; DH = Head
	; CL = Sector number + upper two bit of Cylinder
	; CH = Cylinder number Bits 7-0
	; ES = Transfer Segment
	; BX = Transfer Offset
	; AL = Sector Transfer Count
	;
	; LBA or Packet info is sent as header in DS:SI
	; Simular to what device drivers use.
	;
	;
	;
    ;---------------------------------------------------------------------
    ;| 00h    BYTE    packet size >=16 (10h)                             |
    ;|                Packet sizes less than above shall be rejected     |
    ;|                with AH=01 and CF=1                                |
    ;|-------------------------------------------------------------------|
    ;| 01h    BYTE    reserved (0)                                       |
    ;|-------------------------------------------------------------------|
    ;| 02h    BYTE    number of blocks to transfer (max 127 - 07Fh)      |
    ;|                >=128(80h) shall be rejected with CF=1 & AH=01     |
    ;|                unless =255(FFh) then use count at 18h             |
    ;|-------------------------------------------------------------------|
    ;| 03h    WORD    reserved byte do not use                           |
    ;|-------------------------------------------------------------------|
    ;| 04h    DWORD   -> 32-bit transfer buffer (XFERSEG:XFEROFS)        |
    ;|                If this =FFFF:FFFF then use 64-Bit mode at 10h     |
    ;|-------------------------------------------------------------------|
    ;| 08h    QWORD   starting abs block number: non-LBA devices, use    |
    ;|        LBA=(((C1*H0)+H1)*S0)+S1-1                                 |
    ;|        C1 = SELECTED CYLINDER                                     |
    ;|        H0 = TOTAL NUMBER OF HEADS (MAX + 1)                       |
    ;|        H1 = SELECTED HEAD NUMBER                                  |
    ;|        S0 = MAX SECTOR NUMBER                                     |
    ;|        S1 = SELECTED SECTOR NUMBER                                |
    ;|        We only use 32-Bits of this 64-Bit number though           |
    ;|-------------------------------------------------------------------|
    ;| 10h    QWORD   64-bit flat address of Transfer address buffer     |
    ;|                used if DWORD at 04h is FFFFh:FFFFh                |
    ;|-------------------------------------------------------------------|
    ;| 18     DWORD   Total blocks to transfer when byte at 2 = FFh      |
    ;|-------------------------------------------------------------------|
    ;| 1C     DWORD   Reserved and shall be 0                            |
    ;---------------------------------------------------------------------


	; Check for whether there is an HD port present.

		CALL SAVEREGS     ; Save registers for this call
		CALL LF           ; Print Line Feed

RUNONE		MOV DX,[CS:DRIVEHEAD]
		IN  AL,DX
		AND AL,0EFH
		OUT DX,AL
		CALL DELAY
		IN  AL,DX
		CMP AL,0FFH       ; Sanity check for port here
		JNE  TESTHERE
		JMP NOTHERE
TESTHERE	MOV AL,0A5H
		MOV DX,[CS:SECTORCOUNT]
		OUT DX,AL
		IN  AL,DX
		CMP AL,0FFH       ; Another check for port here
		JNE GOID0
		JMP NOTHERE

GOID0           MOV BYTE [CS:ISMSTR],00H    ;Current drive master
                MOV BYTE [CS:ISLBA],00H     ;Current drive LBA mode
                MOV BYTE [CS:ISREM],00H     ;Current drive removable
		CALL IDDRIVE                ; Use EC command to ID drive
		CMP AL,00H                  ; AL=Nmbr Drvs ID'd for use.
		JE GOID1     ; If none then go on to next drive

                INC BYTE [CS:LOCALDRVS]     ; Kinda Obvious
                PUSH DS
		MOV AX,040H                 ; BIOS data segment
		MOV DS,AX
		MOV AL,[075H]               ; HD Count
		OR AL,080H
		MOV [CS:P0MDRIVE],AL        ; Drive Number New Drive
		INC BYTE [075H]             ; Inc Drive Count
		POP DS

;CONTINUE HERE WITH THE COPY P0M PARMS AND SET P0MDRIVE IF USE.

		PUSH AX                     ; Copy Current parms to P0MSTR
                MOV AX,[CS:BASE]
                MOV [CS:P0BASE],AX
                MOV AL,[CS:ISMSTR]
                MOV [CS:P0MMSTR],AL
                MOV AL,[CS:ISLBA]
                MOV [CS:P0MLBA],AL
                MOV AL,[CS:ISREM]
                MOV [CS:P0MREM],AL
                MOV AX,[CS:MYCYLINDERS]
                MOV [CS:P0MCYL],AX
                MOV AX,[CS:MYHEADS]
                MOV [CS:P0MHEADS],AX
                MOV AX,[CS:MYSECTORS]
                MOV [CS:P0MSECTORS],AX
                POP AX

;THEN MODIFY THE ISMSTR AND RESCAN FOR THE SLAVE THIS TIME.

GOID1           MOV BYTE [CS:ISMSTR],01H
                MOV BYTE [CS:ISLBA],00H
                MOV BYTE [CS:ISREM],00H
		CALL IDDRIVE
		CMP AL,00H
		JNE GOODID1
		JMP CHKDRVS

;THEN COPY PARMS TO P0S AND SET P0SDRIVE TO NEXT IF USE.


GOODID1         INC BYTE [CS:LOCALDRVS]
                PUSH DS
		MOV AX,040H            ; Bios Data Segment
		MOV DS,AX
		MOV AL,[075H]          ; HD Count
		OR AL,080H
		MOV [CS:P0SDRIVE],AL
		INC BYTE [075H]        ; New HD Count
GOID1POP        POP DS

		PUSH AX
                MOV AX,[CS:BASE]       ; Save Base Adress
                MOV [CS:P0BASE],AX
                MOV AL,[CS:ISMSTR]
                MOV [CS:P0SMSTR],AL
                MOV AL,[CS:ISLBA]
                MOV [CS:P0SLBA],AL
                MOV AL,[CS:ISREM]
                MOV [CS:P0SREM],AL
                MOV AX,[CS:MYCYLINDERS]
                MOV [CS:P0SCYL],AX
                MOV AX,[CS:MYHEADS]
                MOV [CS:P0SHEADS],AX
                MOV AX,[CS:MYSECTORS]
                MOV [CS:P0SSECTORS],AX
                POP AX

;THEN CHECK FOR WHETHER ANY WERE USED.
;WILL BE 00H OR 0FFH IS NOT USED.
;IF ARE THEN INSTALL MOD ELSE EXIT.

CHKDRVS         CMP BYTE [CS:LOCALDRVS],00H
                JE NODRVS

		PUSH DS
		XOR AX,AX
		MOV DS,AX
		MOV AX,[04CH]          ; Bios Int 13 Ofs
		MOV DX,[04EH]          ; Bios Int 13 Seg
		MOV [CS:OFS13],AX
		MOV [CS:SEG13],DX

		MOV AX,L13             ; Local Int 13
		PUSH CS
		POP DX

		MOV [04CH],AX          ; Now runs Local Int 13
		MOV [04EH],DX

		PUSH DX
		CALL LF
		MOV DX,OLD13
		CALL PRN_DX            ; Print CS:DX String AsciiZ
		MOV DX,[CS:SEG13]
		MOV [CS:PRNWORD],DX
		CALL PRN_WORD          ; Print WORD in HEX
		CALL LF                ; Prn LineFeed
		CALL PRN_SEG           ; Prn This Segment
		CALL PRN_FN            ; Prn 
		MOV DX,MYMODIN
		CALL PRN_DX
		POP DX
		POP DS

;	THIS IS WHERE THE REAL PARTITION SECTOR GETS LOADED AND JUMPED TO

NODRVS		CALL LF                ; Same exit whether BIOS mod 
		XOR AX,AX              ; loaded or not.
		MOV ES,AX
		MOV BX,07C00H          ; Load at 0:7C00
		MOV DL,80H
		MOV DH,00H
		MOV CL,02H
		MOV CH,00H
		MOV AL,01H
		MOV AH,02H
		INT 013H		

		CALL	RTNREGS        ; Give the regs back

		DB	0EAH           ; Far jump 0:7C00
		DW	07C00H
		DW	00H

		JMP QUIT

MYMODIN		DB	'NewPort BIOS MOD INSTALLED',0DH,0AH,'$'

NOTHERE 	MOV DX,NTHR
		CALL PRN_DX
		JMP NODRVS
; 		LOCAL INT 13 WORK BEGINS HERE

WEBUSY		DB	00H            ; Busy Count
OLDMS		DB	00H            ; Old MSLBA register contents
THISFUNC	DB	00H            ; Duhh
THISAX		DW	00H            ; ReDuhh

L13		CMP DL,[CS:P0MDRIVE]
		JE P0MOURS             ; Is our P0MSTR
		CMP DL,[CS:P0SDRIVE]
		JE P0SOURS             ; Is our P0MSL
                JMP NOTOURS

P0MOURS         PUSH AX
;                MOV AX,[CS:P0BASE]    ; For later when this covers
;                MOV [CS:BASE],AX      ; multiple ports
                                       ; Include P0Set for both HD this Port
                                       ; Will adjust all regs
                MOV AL,[CS:P0MMSTR]    ; Port 0 Master info
                MOV [CS:ISMSTR],AL
                MOV AL,[CS:P0MLBA]
                MOV [CS:ISLBA],AL
                MOV AL,[CS:P0MREM]
                MOV [CS:ISREM],AL
                MOV AX,[CS:P0MCYL]
                MOV [CS:MYCYLINDERS],AX
                MOV AX,[CS:P0MHEADS]
                MOV [CS:MYHEADS],AX
                MOV AX,[CS:P0MSECTORS]
                MOV [CS:MYSECTORS],AX
                POP AX
                JMP ISOURS

P0SOURS         PUSH AX
;                MOV AX,[CS:P0BASE]    ; For later when this covers
;                MOV [CS:BASE],AX      ; multiple ports
                                       ; Include P0Set for both HD this Port
                                       ; Will adjust all regs
                MOV AL,[CS:P0SMSTR]    ; Port 0 Slave Info
                MOV [CS:ISMSTR],AL
                MOV AL,[CS:P0SLBA]
                MOV [CS:ISLBA],AL
                MOV AL,[CS:P0SREM]
                MOV [CS:ISREM],AL
                MOV AX,[CS:P0SCYL]
                MOV [CS:MYCYLINDERS],AX
                MOV AX,[CS:P0SHEADS]
                MOV [CS:MYHEADS],AX
                MOV AX,[CS:P0SSECTORS]
                MOV [CS:MYSECTORS],AX
                POP AX

ISOURS		CLI
		MOV [CS:THISFUNC],AH
		MOV [CS:THISAX],AX
		CALL SAVEREGS          ; My registers, save my registers
		PUSH AX
		MOV AX,01681H
		INT 02FH               ; Go away windows I'm busy
		POP AX
		PUSH AX
		PUSH BX
		PUSH DI
		MOV BL,AH
		XOR BH,BH
		MOV DI,FUNCBUF
		MOV AL,[CS:BX+DI]
INC_AL		INC AL                 ; Inc called function buffer count
		MOV [CS:BX+DI],AL
		CMP AL,00H
		JNE BUSYLOOP           ; If loop to 0 then ReInc
		JMP INC_AL
BUSYLOOP	MOV AL,[CS:WEBUSY]
		CMP AL,00H
		JE NOTBUSY

		PUSH DX                ; Print diasgnostic error
		MOV DX,DRVBSY          ; message if driver is allready
		CALL LF                ; with something else.
		CALL PRN_DX
		CALL DELAY
		POP DX
                PUSH AX
                XOR AX,AX
                INC AH
                INT 016H
                CMP AL,01BH            ; Check for ESC
                JNE NOKEY
                DEC BYTE [CS:WEBUSY]   ; If ESC then Dec WEBUSY Error chking
NOKEY           POP AX
		JMP BUSYLOOP

NOTBUSY		INC AL
		MOV [CS:WEBUSY],AL     ; Now set are busy flag
		MOV DX,[CS:DRIVEHEAD]
		IN AL,DX
		MOV [CS:OLDMS],AL      ; Save MSLBA state
                CALL SETMSLBA          ; Set MS and LBA bits
		POP DI
		POP BX
		POP AX
                                        ; Dispatch table
                                        ; Will be redone when there is
                                        ; time for now it works.
		CMP AH,00H
		JE L_1300              ; Drive reset
		CMP AH,01H
		JE L_1301              ; Drive status
		CMP AH,02H
		JE L_1302              ; Read sectors CHS
		CMP AH,03H
		JE L_1303              ; Write Sectors CHS
		CMP AH,04H
		JE L_1304              ; Verify Sectors CHS
		CMP AH,08H
		JE L_1308              ; ID Drive
		CMP AH,09H
		JE L_1309              ; Set parms
		CMP AH,0AH
		JE L_130A              ; Read Long CHS
		CMP AH,0BH
		JE L_130B              ; Write Long CHS
		CMP AH,0CH
		JE L_130C
		CMP AH,0DH
		JE L_1300              ; Drive Reset
		CMP AH,010H
		JE L_1300
		CMP AH,015H
		JE L_1315
		CMP AH,016H
		JE L_1300

		CMP AH,025H
		JE L_1325

		CMP AH,041H            ; Extended BIOS Interface?
		JE L_1341
		CMP AH,042H            ; Extended read PACKET based
		JE L_1342
		CMP AH,043H            ; Extended write PACKET based
		JE L_1343
		CMP AH,044H            ; Extended verify PACKET based
		JE L_1344
		CMP AH,047H
		JE L_1347
		CMP AH,048H            ; Extended Get Drive Paramaters
		JE L_1348
		CMP AH,0FFH            ; Return DumpFunc
		JE L_13FF

		MOV AH,01H             ; If none of above then return
		JMP INTDONE            ; with bad command

NOTOURS		NOP

JMPFAR:        	DB	0EAH
OFS13:		DW	00H
SEG13:		DW	00H
		JMP QUIT


L_1300		JMP L1300

L_1301		JMP L1301

L_1302		JMP L1302

L_1303		JMP L1303

L_1304		JMP L1304

L_1308		JMP L1308

L_1309		JMP L1309

L_130A		JMP L130A

L_130B		JMP L130B

L_130C		JMP L130C

L_1315		JMP L1315

L_1325		JMP L1325

L_1341		JMP L1341

L_1342		JMP L1342

L_1343		JMP L1343

L_1344		JMP L1344

L_1347		JMP L1347

L_1348		JMP L1348

L_13FF		JMP L13FF


INTDONE		MOV [CS:AH_IN],AH
		MOV DX,[CS:DRIVEHEAD]
		MOV AL,[CS:OLDMS]
		OUT DX,AL              ; Rewrite old MSLBA
		CALL DELAY             ; Wait 400 NS
		CALL BSY0              ; Delay here, Unknown why, But helps
		OUT DX,AL              ; Rewrite Old MSLBA again
		CALL DELAY
;		CALL BSY0
		MOV AL,[CS:WEBUSY]
		DEC AL                 ; Dec webusy cause we are done
		MOV [CS:WEBUSY],AL
INTDONEREGS	PUSH AX
		MOV AX,01682H
		INT 02FH                   ; Hey Windows, Were done.
		POP AX
		CALL RTNREGS               ; Here have your regs back
		CMP BYTE [CS:THISFUNC],041H ;Func 41h Exits funny
		JE NOERREXIT
		CLC
		CMP AH,00H
		JE NOERREXIT
		STC
NOERREXIT	STI                    ; Its messy but it puts flags on stk
		PUSHF                  ; where we want them
		MOV [CS:TEMPAX],AX
		POP AX                 ; the flags we just pushed
		MOV [CS:TEMPFLG],AX

		POP AX                 ; Offset of IRET
         	MOV [CS:TEMPOFS],AX
		POP AX                 ; Segment of IRET
		MOV [CS:TEMPSEG],AX

		POP AX                 ; Flags of IRET - Disposed of

		MOV AX,[CS:TEMPFLG]    ; Pull out temp flags
		PUSH AX                ; Push in place of the entry flags
		MOV AX,[CS:TEMPSEG]
		PUSH AX                ; Put the Segment back
		MOV AX,[CS:TEMPOFS]
		PUSH AX                ; Put offset back
		MOV AX,[CS:TEMPAX]     ; Put AX back
		IRET                   ; You are the weakest IRQ - Goodbye.

TEMPAX:		DW	00H
TEMPOFS:	DW	00H
TEMPSEG:	DW	00H
TEMPFLG:	DW	00H

L1300                          ; Reset Hard Disk
		JMP L130D

L1301				   ; Drive Status
		CLC
		MOV AH,[CS:ERRORBYTE]
		JMP INTDONE

WAITCOUNT:	DW	00H

L1302CMDERR:	DB	'READ COMMAND TIMEOUT ERROR',0DH,0AH,'$'

L1302ERR:	DB	00H

L1342           ; Extended read
		CALL PARSEPACKET   ; SETS PARMS FOR READ
		JC L1342ERRDONE
		JMP L1302CMD
L1342ERRDONE	JMP L1302ERRDONE

; MAYBE MAKE A GENERIC READ CALLABLE BLOCK - NOT good idea for clarity

L1302		; Read Sectors
                CALL RWSETUP           ; setup registers for read
L1302CMD	NOP     ; L1342 jump in here

L1302GO		MOV BYTE [CS:L1302ERR],00H ; errors so far
		MOV DX,[CS:COMMAND]
		MOV AL,020H                 ; send read sector command
		OUT DX,AL
		CALL BSY0                   ; wait for bsy=0
		JC L1342ERRDONE
L1302CONTINUE	MOV AL,[CS:XFERCOUNT]       ; From AL or packet
		CBW
		MOV DI,AX
		MOV DX,[CS:XFERSEG]         ; From ES or packet
		MOV ES,DX
		MOV DX,[CS:DATAREG]
		MOV BX,[CS:XFEROFS]         ; From BX or Packet
L1302MULTLOOP	MOV SI,00H
		MOV WORD [CS:WAITCOUNT],00H

L1302DRQ	CALL DRQ     ; Is data ready DRQ returns DRQ bit in carry
		JC L1302SECLOOP
		INC WORD [CS:WAITCOUNT]
		CMP WORD [CS:WAITCOUNT],00H ; wait alot of tries then timeout
		JE L1302TIMEOUT
		JMP L1302DRQ

L1302TIMEOUT	MOV AH,04H
		MOV AL,[CS:XFERCOUNT]
		JMP L1302ERRDONE

L1302SECLOOP	IN AX,DX
		MOV [ES:BX+SI],AX      ; I use offsets for clarity
		INC SI                 ; the purpose of this code is
		INC SI                 ; educational so I do
		CMP SI,0200H           ; 256 (0x100) word reads
		JL L1302SECLOOP
                INC BYTE [CS:XFERD]    ; Increment Transferred count
;                CALL DEVERR
;                JC L1302ERRDONE
       		ADD BX,0200H           ; Add 1 sector size to offset
		DEC DI                 ; decrement sector count remaining
		CMP DI,00H             ; 0 ?
		JNE L1302MULTLOOP      ; If not then do this circus again
		XOR AH,AH              ; Return code for no errors
		MOV AL,[CS:XFERD]
		CMP BYTE [CS:THISFUNC],042H ; Packet command ?
		JE L1342DONE
L1302ERRDONE	MOV BYTE [CS:L1302ERR],00H
		MOV [CS:AL_IN],AL      ; AL holds transfer count
		JMP INTDONE
L1342DONE       MOV [SI+02H],AL        ; Packet 2nd byte holds xfer count
                JMP INTDONE



L1303CMDERR	DB	'WRITE COMMAND TIMEOUT ERROR',0DH,0AH,'$'
L1303ERR        DB      00H

L1343           ; Extended write
		CALL PARSEPACKET   ; SETS PARMS FOR READ
		JC L1343ERRDONE
		JMP L1303CMD
L1343ERRDONE	JMP L1303ERRDONE

; MAYBE MAKE A GENERIC WRITE CALLABLE BLOCK

L1303		   ; Write Sectors
		CALL RWSETUP           ; setup registers for write
L1303CMD	MOV DX,[CS:COMMAND]
		MOV AL,030H
		OUT DX,AL              ; send write command
		CALL BSY0              ; wait for drive busy = 0
		JNC L1303CONTINUE
		PUSH DX
		MOV DX,L1303CMDERR
		CALL PRN_DX            ; Print warning about cmd error
		POP DX
		JMP L1303TIMEOUT

L1303CONTINUE;	MOV WORD [CS:WAITCOUNT],00H
		MOV AL,[CS:XFERCOUNT]       ; Transfer Count
		CBW
		MOV DI,AX
		MOV DX,[CS:XFERSEG]         ; Transfer Segment
		MOV ES,DX
		MOV DX,[CS:DATAREG]
		MOV BX,[CS:XFEROFS]         ; Transfer Offset
L1303MULTLOOP	MOV SI,00H
		MOV WORD [CS:WAITCOUNT],00H

L1303DRQ	CALL DRQ1     ; Not otherwise busy and data ready.
		JNC L1303LOOP
		MOV AL,[CS:STATBYTE]
		MOV [CS:PRNBYTE],AL
		CALL SPC
		CALL PRN_BYTE
		CALL PRN_BYTE
		CALL SPC
		CALL DELAY
		INC WORD [CS:WAITCOUNT]
		CMP WORD [CS:WAITCOUNT],03H
		JE L1303TIMEOUT
		JMP L1303DRQ

L1303TIMEOUT	MOV AH,04H
		MOV AL,[CS:XFERD]
		JMP L1303ERRDONE

L1303LOOP	MOV AX,[ES:BX+SI]
		OUT DX,AX
		INC SI
		INC SI
		CMP SI,0200H
		JL L1303LOOP           ; Do 256 Word writes.
                INC BYTE [CS:XFERD]    ; Increment transferred.
;                CALL DEVERR
;                JC L1303ERRDONE
		ADD BX,0200H           ; Add sector to Offset
		DEC DI
		CMP DI,00H
		JNE L1303MULTLOOP ; Please note that there is little error
		                  ; checking done on each write here
		XOR AH,AH              ; Indicate no error
		MOV AL,[CS:XFERD]      ; Transferred count
		CMP BYTE [CS:THISFUNC],043H
		JE L1343DONE
L1303ERRDONE	MOV BYTE [CS:L1303ERR],00H
		MOV [CS:AL_IN],AL ; Al holds Xfer count
		JMP INTDONE
L1343DONE       MOV [SI+02H],AL   ; Packet + 2 for count
                JMP INTDONE

L13X4ERR        DB      00H


L1344		   ; Extended Verify
		CALL PARSEPACKET
		JMP L1304CMD

L1304		CALL RWSETUP      	   ; Verify Sectors
L1304CMD        MOV BYTE [CS:L13X4ERR],00H	
                MOV DX,[CS:COMMAND]
		MOV AL,040H
		OUT DX,AL
		CALL DELAY                  ; Delay at least 400Ns.
		CALL BSY0                   ; Are we unbusy yet?
		JC L13X4TIMEOUT
		MOV DX,[CS:STATUS]
		IN AL,DX
		AND AL,01H                  ; Error Bit is 0
		CMP AL,01H                  ; Is it set?
		JE L13X4ERROR
		MOV AL,[CS:AL_IN]
		MOV AH,00
                CLC
         	JMP INTDONE

L13X4ERROR      NOP
L13X4TIMEOUT	CMP BYTE [CS:THISFUNC],044H
                JE L1344ERROR
                MOV AL,01H
                MOV AH,04H
                STC
                JMP INTDONE
L1344ERROR      MOV BYTE [SI+02H],1
                STC
                JMP INTDONE

L1308				   ; Drive Parms
                PUSH DX
                PUSH CS
                POP DX
                MOV [CS:XFERSEG],DX
                MOV DX,MYBUFFER
                MOV [CS:XFEROFS],DX
                POP DX

                CALL CALLIDLOOP   ; This does ID info to XferSeg:XFerOfs

		PUSH DS
		MOV AX,040H
		MOV DS,AX

          	MOV DL,[075h]     ; Total HD Count
L1308DLIN	MOV [CS:DL_IN],DL
		POP DS
		MOV CX,[CS:MYCYLINDERS]
		XCHG CL,CH
		SHL CL,1
		SHL CL,1
		SHL CL,1
		SHL CL,1
		SHL CL,1
		SHL CL,1
		ADD CL,[CS:MYSECTORS]
		MOV DH,[CS:MYHEADS]
		DEC DH
		MOV DL,[CS:DL_IN] ; The preceeding converts raw to register
		XOR AX,AX         ; format for 10-Bit cylinder plus other
		XOR BX,BX         ; info as needed.
                CMP BYTE [CS:ISREM],00H
                JE L1308NOTREM
                MOV BL,010H
L1308NOTREM	MOV [CS:AX_IN],AX ; Store info for retrieval in INTDONE
		MOV [CS:BX_IN],BX
		MOV [CS:CX_IN],CX
		MOV [CS:DX_IN],DX
		MOV [CS:AH_IN],AH
		MOV [CS:BH_IN],BH
		MOV [CS:CH_IN],CH
		MOV [CS:DH_IN],DH
		MOV [CS:AL_IN],AL
		MOV [CS:BL_IN],BL
		MOV [CS:CL_IN],CL
		MOV [CS:DL_IN],DL

		JMP INTDONE


L1309		; 	initialize device parms? done for spinrite.
		MOV BYTE [AH_IN],00H
		CLC
		JMP INTDONE


L130ACMDERR:	DB	'READ LONG COMMAND TIMEOUT ERROR',0DH,0AH,'$'

L130A_AL        DB      00H

L130AERROR      MOV AH,01H
                MOV AL,00H
                MOV [CS:L130AERR],AL
                JMP L130A_ERROR

L130AERR:	DB	00H

L130A		; Read Sectors long - Sector Data + 4 Bytes ECC
                CMP AL,01H
                JG L130AERROR
		MOV BYTE [CS:L130AERR],00H		
		CALL RWSETUP      ; Setup Registers
		MOV DX,[CS:COMMAND]
		MOV AL,022H
		OUT DX,AL         ; Issue command
		CALL BSY0DRQ1
		JNC L130ACONTINUE
		INC BYTE [CS:L130AERR]
		PUSH DX
		MOV DX,L130ACMDERR
		CALL PRN_DX
		POP DX
		JMP L130ATIMEOUT

L130ACONTINUE	MOV DX,[CS:XFERSEG]
		MOV ES,DX
		MOV DX,[CS:DATAREG]
		MOV BX,[CS:XFEROFS]
L130AMULTLOOP	MOV SI,00H
		MOV WORD [CS:WAITCOUNT],00H

L130ADRQ	CALL DRQ
		JC L130ASECLOOP
		MOV AL,[CS:STATBYTE]
		MOV [CS:PRNBYTE],AL
		INC WORD [CS:WAITCOUNT]
		CMP WORD [CS:WAITCOUNT],03H
		JE L130ATIMEOUT
		JMP L130ADRQ

L130ATIMEOUT	MOV AH,04H
		MOV AL,01H
		JMP L130AERRDONE

L130ASECLOOP	IN AX,DX
		MOV [ES:BX+SI],AX
		INC SI
		INC SI
		CMP SI,0200H
		JL L130ASECLOOP

L130AECCLOOP	IN AX,DX
		MOV [ES:BX+SI],AL
		INC SI
		CMP SI,0204H
		JL L130AECCLOOP

                INC BYTE [CS:XFERD]
		XOR AH,AH
		MOV AL,[CS:AL_IN]
L130AERRDONE	MOV BYTE [CS:L130AERR],00H
L130A_ERROR	MOV [CS:AL_IN],AL
		JMP INTDONE


L130BCMDERR	DB	'WRITE LONG COMMAND TIMEOUT ERROR',0DH,0AH,'$'


L130BERROR      MOV AH,01H
                MOV AL,00H
                MOV [CS:L130BERR],AL
                JMP L130BERRDONE

L130BERR        DB      00H


L130B		; Write Sectors long
                CMP AL,01H
                JG L130BERROR
		MOV BYTE [CS:L130BERR],00H		
		CALL RWSETUP
		MOV DX,[CS:COMMAND]
		MOV AL,032H
		OUT DX,AL
		CALL BSY0DRQ1
		JNC L130BCONTINUE
		PUSH DX
		MOV DX,L130BCMDERR
		CALL PRN_DX
		POP DX
		JMP L130BTIMEOUT

L130BCONTINUE;	MOV WORD [CS:WAITCOUNT],00H
		MOV DX,[CS:XFERSEG]
		MOV ES,DX
		MOV DX,[CS:DATAREG]
		MOV BX,[CS:XFEROFS]
L130BMULTLOOP	MOV SI,00H
		MOV WORD [CS:WAITCOUNT],00H

;		CALL DRQ1

L130BDRQ	CALL BSY0DRQ1
		JNC L130BSECLOOP
		MOV AL,[CS:STATBYTE]
		MOV [CS:PRNBYTE],AL
		CALL SPC
		CALL PRN_BYTE
		CALL SPC
		CALL DELAY
		INC WORD [CS:WAITCOUNT]
		CMP WORD [CS:WAITCOUNT],03H
		JE L130BTIMEOUT
		JMP L130BDRQ

L130BTIMEOUT	MOV AH,04H
		MOV AL,01H
		JMP L130BERRDONE

L130BSECLOOP	MOV AX,[ES:BX+SI]
		OUT DX,AX
		INC SI
		INC SI
		CMP SI,0200H
		JL L130BSECLOOP

L130BECCLOOP	MOV AL,[ES:BX+SI]
		OUT DX,AL
		INC SI
		CMP SI,0204H
		JL L130BECCLOOP

                INC BYTE [CS:XFERD]
		XOR AH,AH
		MOV AL,[CS:AL_IN]

L130BERRDONE	MOV [CS:AL_IN],AL
		JMP INTDONE



L1347		CALL PARSEPACKET
		JMP L130CCMD

L130C		   ; Seek to Cyl
		CALL RWSETUP
L130CCMD	MOV DX,[CS:COMMAND]
		MOV AL,070H
		OUT DX,AL
		CALL DELAY
		CALL BSY0DRDY1
		CALL DEVERR
		JNC L130CGOOD		
		MOV AH,04H
L130CGOOD	JMP INTDONE
	

L130D;          Reset drive
                CMP BYTE [CS:ISREM],00H
                JNE L130DNOREM
                MOV DX,[CS:COMMAND]
                MOV AL,0DEH
                OUT DX,AL
                CALL BSY1
                CALL BSY0
L130DNOREM      MOV DX,[CS:SECTORCOUNT]
                MOV AL,00H
                OUT DX,AL    ;+2
                INC DX
                OUT DX,AL    ; +3
                INC DX
                OUT DX,AL    ; +4
                INC DX
                OUT DX,AL    ; +5
                INC DX
                IN AL,DX
                AND AL,0F0H
                OUT DX,AL    ; +6
                INC DX
                MOV AL,10H
                OUT DX,AL    ; +7
                CALL BSY1
                CALL BSY0
L130DDONE       MOV AH,00H
                CLC
                JMP INTDONE


MYCYLHDAX:	DW	00H
MYCYLHDDX:	DW	00H

L1315		MOV AX,[CS:MYCYLINDERS]
		MOV BL,[CS:MYHEADS]
		XOR BH,BH
		MUL BX
		MOV [CS:MYCYLHDAX],AX
		MOV [CS:MYCYLHDDX],DX
		MOV BX,[CS:MYSECTORS]
		MUL BX
		MOV [CS:DX_IN],AX
		MOV [CS:CX_IN],DX
		MOV AX,[CS:MYCYLHDDX]
		MUL BX
		ADD [CS:CX_IN],AX
		MOV CX,[CS:CX_IN]
		MOV DX,[CS:DX_IN]
		MOV [CS:CL_IN],CL
		MOV [CS:CH_IN],CH
		MOV [CS:DL_IN],DL
		MOV [CS:DH_IN],DH

		JMP INTDONE


L1325		; Identify Drive

                PUSH DX
                PUSH CS
                POP DX
                MOV [CS:XFERSEG],DX
                MOV DX,MYBUFFER
                MOV [CS:XFEROFS],DX
                POP DX
                CALL CALLIDLOOP
		MOV BX,[CS:ES_IN]
		MOV ES,BX
		MOV BX,[CS:BX_IN]
		MOV DI,BX
		MOV SI,MYBUFFER
		XOR BX,BX
L1325LOOP	MOV AX,[CS:SI+BX]
		MOV [ES:DI+BX],AX
		INC BX
		INC BX
		CMP BX,0200H
		JL L1325LOOP
		MOV AH,00H
		JMP INTDONE

L1341		   ; Extended info
		CMP BYTE [CS:ISLBA],00H
;		CMP BYTE [CS:ISLBA],01H
		JE L1341ERROR
		CALL RTNREGS
		CMP BX,055AAH
		JNE L1341ERROR
		MOV BX,0AA55H
		MOV CX,01H
		MOV AL,00H
		MOV AH,01H
		XOR DH,DH
		CALL SAVEREGS
		CLC
		JMP INTDONE

L1341ERROR	MOV AH,01H
                STC
                JMP INTDONE


L1348ERROR	MOV AH,01H
                STC
		JMP INTDONE

L1348		   ; Extended get parms
		CMP BYTE [CS:ISLBA],00H
		JE L1348ERROR

                PUSH DX
                PUSH CS
                POP DX
                MOV [CS:XFERSEG],DX
                MOV DX,MYBUFFER
                MOV [CS:XFEROFS],DX
                POP DX

                CALL CALLIDLOOP

		CALL RTNREGS
		CMP WORD [SI],01AH
		JL L1348ERROR
		CMP WORD [SI],01DH
		JLE L1348_1A
		MOV WORD [SI],01EH
		JMP L1348_GO
L1348_1A	MOV WORD [SI],01AH
L1348_GO	MOV AX,[CS:MYBUFFER+06CH]
;                MOV AX,[CS:MYCYLINDERS]
              	MOV [SI+04H],AX
		MOV AX,[CS:MYBUFFER+06EH]
;                MOV AH,00H
;                MOV AL,[CS:MYHEADS]
		MOV [SI+08H],AX
		MOV AX,[CS:MYBUFFER+070H]
;                MOV AH,00H
;  		 MOV AL,[CS:MYSECTORS]
		MOV [SI+0CH],AX

		MOV WORD [SI+06H],00H
		MOV WORD [SI+0AH],00H
		MOV WORD [SI+0EH],00H

		MOV AX,[CS:MYBUFFER+078H]
		MOV [SI+010H],AX

		MOV AX,[CS:MYBUFFER+07AH]
		MOV [SI+012H],AX

		MOV WORD [SI+14H],00H
		MOV WORD [SI+16H],00H

		MOV WORD [SI+018H],0200H
		CMP WORD [SI],01AH
		JE L1348SZ26
		MOV WORD [SI+01AH],0FFFFH
		MOV WORD [SI+01CH],0FFFFH
L1348SZ26	MOV WORD [SI+02H],01H
;                MOV AX,


		MOV AH,00H
		JMP INTDONE


L13FF           MOV SI,FUNCBUF
                PUSH CS
                MOV [CS:SI_IN],SI
                POP SI
                MOV [CS:DS_IN],SI
                JMP INTDONE


MSLBAREG:     DB   00H
MSLBACOUNT:   DB   00H

SETMSLBA      MOV BYTE [CS:MSLBACOUNT],00H
MSLBALOOP     NOP
              CALL BSY0
              JNC MSLBAGO
              CALL DELAY
              INC BYTE [CS:MSLBACOUNT]
              CMP BYTE [CS:MSLBACOUNT],00H
              JE MSLBAGO
              JMP MSLBALOOP

MSLBAGO       MOV DX,[CS:DRIVEHEAD]
              MOV AL,0A0H
              CMP BYTE [CS:ISMSTR],00H
              JE MSLNO
              OR AL,0B0H
MSLNO         OUT DX,AL
              CALL DELAY
ISMSLBA       CMP BYTE [CS:ISLBA],00H
              JE NOLBA
              OR AL,0E0H
              OUT DX,AL
              CALL DELAY
NOLBA         MOV BYTE [CS:XFERD],00H
              RET


RWSETUP		; PREPARE FOR READING/WRITING/VERIFYING OF SECTORS

		MOV AX,[CS:ES_IN]
		MOV [CS:XFERSEG],AX
		MOV AX,[CS:BX_IN]
		MOV [CS:XFEROFS],AX

		MOV AL,[CS:AL_IN]
		MOV [CS:XFERCOUNT],AL
		MOV DX,[CS:SECTORCOUNT]
		OUT DX,AL
		CMP BYTE [CS:ISLBA],00H
		JNE RWLBA
RWCHS		MOV AL,[CS:CL_IN]
		AND AL,03FH
		MOV DX,[CS:SECTORNUMBER]
                MOV [CS:SECTOR_IN],AL
		OUT DX,AL
		MOV AL,[CS:CL_IN]
		SHR AL,1
		SHR AL,1
		SHR AL,1
		SHR AL,1
		SHR AL,1
		SHR AL,1
		MOV DX,[CS:CYLINDERHIGH]
                PUSH AX
                MOV AH,AL
                MOV AL,[CS:CH_IN]
                MOV [CS:CYL_IN],AX
                POP AX
		OUT DX,AL
		MOV DX,[CS:CYLINDERLOW]
		MOV AL,[CS:CH_IN]
		OUT DX,AL

		MOV DX,[CS:DRIVEHEAD]
		MOV BL,[CS:DH_IN]
		IN AL,DX
		AND AL,0F0H
		AND BL,0FH
		OR AL,BL
		OUT DX,AL
                AND AL,0FH
                MOV [CS:HEAD_IN],AL		
		JMP RWSETUPDONE		

CYLHDAX		DW	00H
CYLHDDX		DW	00H
CYLSECAX1	DW	00H
CYLSECDX1	DW	00H
CYLSECAX2	DW	00H
CYLSECDX2	DW	00H

LBA0007		DB	00H
LBA080F		DB	00H
LBA1017		DB	00H
LBA181B		DB	00H

RWLBA

;		FIRST	CYLINDER*HEADS
		XOR AX,AX
		XOR BX,BX
		XOR CX,CX
		XOR DX,DX
		MOV AL,[CS:CH_IN]
		MOV AH,[CS:CL_IN]		; Upper two(2) bits of cylinder
		SHR AH,1		; number in bits 7-6
		SHR AH,1
		SHR AH,1
		SHR AH,1
		SHR AH,1
		SHR AH,1
		MOV BL,[CS:MYHEADS]
		MOV BH,00H
		MUL BX	
					; Multiply by total heads
					; Total goes in DX:AX
					; DX=0 IF UNDER 8 GIG

;       				THEN	ADD HEADS

		MOV BL,[CS:DH_IN]		; Add selected head number
		XOR BH,BH
		ADD AX,BX
		ADC DX,0		; Add with carry from Add AX,BX
		MOV [CS:CYLHDAX],AX
		MOV [CS:CYLHDDX],DX

;        				THEN	* SECTORS/TRK

		MOV AX,[CS:CYLHDAX]
		MOV BL,[CS:MYSECTORS]
		MOV BH,00H
		MUL BX
		MOV [CS:CYLSECAX1],AX
		MOV [CS:CYLSECDX1],DX

		MOV AX,[CS:CYLHDDX]
		MOV BL,[CS:MYSECTORS]
		MOV BH,00H
		MUL BX
		MOV [CS:CYLSECAX2],AX
		MOV [CS:CYLSECDX2],DX

		MOV AX,[CS:CYLSECAX1]
		MOV DX,[CS:CYLSECDX1]
		MOV BX,[CS:CYLSECAX2]
		ADD DX,BX

;				THEN	ADD SECTOR#

		MOV BL,[CS:CL_IN]
		AND BL,03FH
		XOR BH,BH
		ADD AX,BX
		ADC DX,00H

;				THEN 	-1

		DEC AX
		SBB DX,00H

		MOV [CS:LBA0007],AL
		MOV [CS:LBA080F],AH
		MOV [CS:LBA1017],DL
		MOV [CS:LBA181B],DH

		MOV DX,[CS:LBA_00_07]
		MOV AL,[CS:LBA0007]
		OUT DX,AL

		MOV DX,[CS:LBA_08_0F]
		MOV AL,[CS:LBA080F]
		OUT DX,AL

		MOV DX,[CS:LBA_10_17]
		MOV AL,[CS:LBA1017]
		OUT DX,AL

		MOV DX,[CS:LBA_18_1B]
		MOV BL,[CS:LBA181B]
		IN AL,DX
		AND AL,0F0H
		AND BL,0FH
		OR AL,BL
		OUT DX,AL              ; Uses only botton 4 bits of register.

RWSETUPDONE	RET


PARSEPACKET	NOP                    ; NOP helps for reasons unknown
		CMP BYTE [SI],010H     ; Size needs to be atleast 16 (010h)
		JGE SIZEGOOD
PARSEOUT	MOV AH,01H
		STC
		JMP PARSERROR
PARSE64         POP AX
                JMP PARSEOUT

SIZEGOOD        CALL PRNPACKET
                PUSH AX
                MOV AL,[SI+02H]   ; Check transfer size
                CMP AL,07FH       ; Over 127(07Fh) then error for us.
                JG  PARSE64       ; This means 64-Bit mode - Not ready yet.
                CMP AL,00H
                JE PARSE64
                MOV AX,[SI+04H]
                CMP AX,0FFFFH     ; 64-Bit Signature?
                JNE PARSE32
                MOV AX,[SI+06H]
                CMP AX,0FFFFH     ; 64-Bit Signature
                JNE PARSE32
                JMP PARSE64       ; If FFFF:FFFF then is 64-Bit go there
PARSE32		POP AX
                MOV DX,[CS:LBA_00_07]
		MOV AL,[SI+08H]
		OUT DX,AL

		MOV DX,[CS:LBA_08_0F]
		MOV AL,[SI+09H]
		OUT DX,AL

		MOV DX,[CS:LBA_10_17]
		MOV AL,[SI+0AH]
		OUT DX,AL

		MOV DX,[CS:LBA_18_1B]
		MOV BL,[SI+0BH]
		IN AL,DX
		AND AL,0F0H
		AND BL,0FH
		OR AL,BL
		OUT DX,AL

		MOV AX,[SI+04H]
		MOV [CS:XFEROFS],AX

		MOV AX,[SI+06H]
		MOV [CS:XFERSEG],AX

;		MOV DX,[CS:SECTORCOUNT]
		MOV AL,[SI+2]
		MOV [CS:XFERCOUNT],AL
		CLC
PARSERROR	RET


;THIS IS CURRENTLY THE CALLIDLOOP FOR IDDRIVE LOOP
;THIS IS TO CALLABLE FROM IDDRIVE AND L1325
;WITH XFERSEG:XFEROFS SET TO ADDRESS TO BE USED FOR BUFFER
;NO REGISTERES PRESERVED


CALLIDLOOP      CLC
                CALL BSY0
                PUSH AX
                PUSH BX
                PUSH DX
                PUSH DI
                PUSH SI
                PUSH ES

		MOV DX,[CS:COMMAND]
		MOV AL,0ECH		; ID Ata device (Non Packet)
		OUT DX,AL
                CALL DELAY
		CALL BSY0DRDY1
		JC IDLOOPERR
		MOV SI,00H			  ;This is a read loop
		MOV DX,[CS:DATAREG]
		MOV BX,[CS:XFERSEG]
		MOV ES,BX
		MOV BX,[CS:XFEROFS]
IDLOOP		IN  AX,DX
		MOV [ES:BX+SI],AX
		INC SI
		INC SI
		CMP SI,200H
		JL  IDLOOP	; At 0x200 the whole block has been read.

IDLOOPDONE      POP ES
                POP SI
                POP DI
                POP DX
                POP BX
                POP AX

                RET

IDLOOPERR       PUSH DX
                MOV DX,IDLOOPERRSTR
                CALL PRN_DX
                POP DX
                PUSH AX
                MOV AH,00H
                INT 016H
                POP AX
                CALL LF
                STC
                JMP IDLOOPDONE

IDLOOPERRSTR    DB 'DRIVE OR DEVICE NOT FOUND',0DH,0AH
                DB 'PRESS ANY KEY TO CONTINUE',0DH,0AH,00H

IDDRVSTR:
	DB	'PLEASE BE PATIENT FOR A MOMENT WHILE I CHECK FOR DRIVE'
	DB	0AH,0DH
	DB	'MODEL NUMBER WILL BE DISPLAYED BELOW IF FOUND'
	DB	0AH,0DH,'$'


NOGOIDLOOP      PUSH DX
                MOV DX,IDLOOPERRSTR
                CALL PRN_DX
                CALL LF
                POP DX
                MOV AL,00H
                PUSH AX
                MOV AH,00H
                INT 016H
                POP AX
                CALL LF
		JMP ISNN


IDDRIVE		PUSH DX
                CALL LF
		MOV DX,IDDRVSTR
		CALL PRN_DX
                CALL LF
                PUSH CS
                POP DX
                MOV [CS:XFERSEG],DX
                MOV DX,MYBUFFER
                MOV [CS:XFEROFS],DX
		POP DX

GOIDLOOP        CALL BSY0
                CALL SETMSLBA
                CALL CALLIDLOOP
                JC NOGOIDLOOP
		CALL LF

		MOV SI,MYBUFFER
		MOV DI,01BH
MDLLOOP		MOV BX,DI
		SHL BX,1
		MOV CX,[CS:SI+BX]
		MOV AL,CH
		CALL PRN_AL
		MOV AL,CL
		CALL PRN_AL
		INC DI
		CMP DI,46
		JLE MDLLOOP
		CALL LF

		MOV AX,[CS:MYBUFFER+00H]
		AND AX,08000H
		CMP AX,08000H
		JNE ISATA
		JMP QUIT

ISATA		
                MOV AX,[CS:MYBUFFER]
                AND AX,080H
                CMP AX,080H
                JNE NOTREM
                MOV AX,01H
                MOV [CS:ISREM],DL

NOTREM		MOV AX,[CS:MYBUFFER+062H]
		AND AX,0200H
		CMP AX,0200H
		JE GOLBA
		MOV DX,[CS:MYBUFFER+02H]		
		DEC DX
		MOV [CS:MYCYLINDERS],DX
		MOV DX,[CS:MYBUFFER+06H]		
		XOR DH,DH
		MOV [CS:MYHEADS],DL
		MOV DX,[CS:MYBUFFER+0CH]		
		XOR DH,DH
		MOV [CS:MYSECTORS],DL
		JMP IDDONE		

GOLBA
		MOV DX,01H
		MOV [CS:ISLBA],DL
		MOV DX,[CS:DRIVEHEAD]
		IN AL,DX
		OR AL,040H
		OUT DX,AL
		CALL BSY0DRDY1

		MOV DX,[CS:MYBUFFER+02H]
		CMP DX,03FFFH
		JL  NOTOVERCHS
		MOV DX,[CS:MYBUFFER+06H]
		XOR DH,DH
		CMP DX,010H
		JL  NOTOVERCHS
		MOV DX,[CS:MYBUFFER+0CH]
		CMP DX,03FH
		JL  NOTOVERCHS

		MOV DX,03FFH
		MOV [CS:MYCYLINDERS],DX
		MOV DX,0FFH
		MOV [CS:MYHEADS],DL
		MOV DX,03FH
		XOR DH,DH
		MOV [CS:MYSECTORS],DL
		JMP IDDONE

NOTOVERCHS	
		MOV DX,[CS:MYBUFFER+02H]		
		DEC DX
		MOV [CS:MYCYLINDERS],DX
		MOV DX,[CS:MYBUFFER+06H]		
		XOR DH,DH
		MOV [CS:MYHEADS],DL
		MOV DX,[CS:MYBUFFER+0CH]		
		XOR DH,DH
		MOV [CS:MYSECTORS],DL

LBAADJUST
		MOV DX,[CS:MYCYLINDERS]
		CMP DX,03FFH
		JLE IDDONE
		SHR DX,1
		MOV [CS:MYCYLINDERS],DX
		MOV DL,[CS:MYHEADS]
		SHL DL,1
		MOV [CS:MYHEADS],DL
		JMP LBAADJUST

IDDONE		MOV DX,USETHIS
		CALL PRN_DX

DRVYN		MOV AH,00H
		INT 016H
		CMP AL,'Y'
		JE DRVKEY
		CMP AL,'y'
		JE DRVKEY
		CMP AL,'N'
		JE DRVKEY
		CMP AL,'n'
		JE DRVKEY
		CMP AL,01BH
		JNE DRVYN
BADID		MOV AL,'N'
		JMP CHOSEN
DRVKEY		MOV [CS:DRVANS],AL
		CALL PRN_AL

;	CONTINUE TO CHECK KEY CODES FOR YyNn - BckSpc - Esc
;	ONLY ACCEPT LAST TWO IN SECOND HALF OF CHECK.

DRVKEYCHK	MOV AH,00H
		INT 016H
		CMP AL,0DH
		JE CHOSEN
		CMP AL,08H
		JNE DRVKEYCHK
		CALL PRN_AL
		MOV AL,' '
		CALL PRN_AL
		MOV AL,08H
		CALL PRN_AL
		JMP DRVYN
CHOSEN		MOV DL,[CS:DRVANS]
		XOR AL,AL
		CMP DL,'N'
		JE ISNN
		CMP DL,'n'
		JE ISNN
		INC AL

ISNN		NOP
		CALL LF
		RET

DRVANS:		DB	00H

QUIT		CALL LF
		CALL LF
		RETF


VIDINFO:	DW	00H

PRN_AL		PUSH AX
		PUSH BX
		PUSH CX
		MOV AH,0EH
		MOV BX,[CS:VIDINFO]
		MOV CX,1
		INT 010H
		POP CX
		POP BX
		POP AX
		RET

PRN_DX		PUSH AX
		PUSH BX
		PUSH DI
		MOV DI,DX
		MOV AH,0FH
		INT 010H
		MOV BL,0
		MOV [CS:VIDINFO],BX
PRNLOOP		MOV AL,[CS:DI]
		CMP AL,'$'
		JE PRNDONE
		CMP AL,00H
		JE PRNDONE
CALL		PRN_AL
		INC DI
		JMP PRNLOOP
PRNDONE		POP DI
		POP BX
		POP AX
		RET

LF		PUSH DX	
		MOV DX,LFSTR
		CALL PRN_DX
		POP DX
		RET

SPC		PUSH DX	
		MOV DX,PRNSPC
		CALL PRN_DX
		POP DX
		RET

PRNBYTE		DB	00H
PRNWORD		DW	00H

PRN_LO		PUSH AX
		PUSH DX
		PUSH DI
		AND DL,0FH
		MOV DI,DX
		MOV AL,[CS:HEXSET+DI]
		CALL PRN_AL
		POP DI
		POP DX
		POP AX
		RET

PRN_HI		PUSH AX
		PUSH DX
		PUSH DI
		AND DL,0F0H
		SHR DL,4
		MOV DI,DX
		MOV AL,[CS:HEXSET+DI]
		CALL PRN_AL
		POP DI
		POP DX
		POP AX
		RET

PRN_BYTE	PUSH DX
		XOR DX,DX
		MOV DL,[CS:PRNBYTE]
		CALL PRN_HI
		MOV DL,[CS:PRNBYTE]
		CALL PRN_LO
		POP DX
		RET

PRN_WORD	PUSH BX
		MOV BX,[CS:PRNWORD]
		MOV [CS:PRNBYTE],BH
		CALL PRN_BYTE
		MOV [CS:PRNBYTE],BL
		CALL PRN_BYTE
		CALL SPC
		POP BX
		RET

CSEQS:		DB	'INSTALLED AT CS=$'

PRN_SEG		PUSH DX
		MOV DX,CSEQS
		CALL PRN_DX
		PUSH CS
		POP DX
		MOV [CS:PRNWORD],DX
		POP DX
		CALL PRN_WORD
		CALL LF
		RET

FNEQS:		DB	'FUNCBUF AT FN=$'

PRN_FN		PUSH DX
		MOV DX,FNEQS
		CALL PRN_DX
		MOV DX,FUNCBUF
		MOV [CS:PRNWORD],DX
		CALL PRN_WORD
		CALL LF
		POP DX
		RET

;delayloop
DELAY		PUSH DX
		PUSH AX
		MOV DX,[CS:ERRORREG]
		IN  AL,DX
		MOV [CS:ERRORBYTE],AL
;		IN  AL,DX
		IN   AL,0ECh
		OUT  0ECh,AL
		IN   AL,0ECh
		OUT  0ECh,AL
		IN   AL,0ECh
		OUT  0ECh,AL
		IN   AL,0ECh
		OUT  0ECh,AL
		IN   AL,0ECh
		OUT  0ECh,AL
		IN   AL,0ECh
		OUT  0ECh,AL
		IN   AL,0ECh
		OUT  0ECh,AL
		POP AX
		POP DX
		RET		; DELAYED FOR 7 RW's OF TEST PORT-ENOUGH?

                ; All routines named by the status bits they check return
                ; Carry set if condition not met or simply as flag saying
                ; what the current status of thast bits is.
                ; Sometims these rioutines are called for delay alone
                ; and this is all that is needed.

DEVERR   	PUSH DX
		PUSH AX
		CALL DELAY
		MOV DX,[CS:STATUS]
		IN  AL,DX	
		MOV [CS:STATBYTE],AL
		CLC
		AND AL,01H        ; Error Bit in Status Reg.
		CMP AL,01H
		JNE DEVERRCLR
		STC
DEVERRCLR	POP AX
		POP DX
		RET


BSYDRQCOUNT	DD	00H

BSY0DRQ1	MOV DWORD [CS:BSYDRQCOUNT],00H
		PUSH DX
		PUSH AX
BSY0DRQ1LOOP	INC DWORD [CS:BSYDRQCOUNT]
		CMP DWORD [CS:BSYDRQCOUNT],010000H
		JE BSYDRQTIMEOUT
		CALL DELAY
		MOV DX,[CS:STATUS]		   ;bsy clr loop1
		IN  AL,DX
		MOV [CS:STATBYTE],AL
		AND AL,88H
		CMP AL,08H
		JNE BSY0DRQ1LOOP
		CLC
BSYDRQDONE	POP AX
		POP DX
			RET
BSYDRQTIMEOUT	STC
		JMP BSYDRQDONE

BSYDRDYCOUNT	DD	00H

BSY0DRDY1	MOV DWORD [CS:BSYDRDYCOUNT],00H
		PUSH DX
		PUSH AX
BSYDRDYLOOP	INC DWORD [CS:BSYDRDYCOUNT]
		CMP DWORD [CS:BSYDRDYCOUNT],010000H
		JE BSYDRDYTIMEOUT
		CALL DELAY
		MOV DX,[CS:STATUS]		   ;bsy clr loop1
		IN  AL,DX
		MOV [CS:STATBYTE],AL
		AND AL,01H
		CMP AL,01H
		JE BSYDRDYTIMEOUT
		MOV AL,[CS:STATBYTE]
		AND AL,88H
		CMP AL,08H
		JNE BSYDRDYLOOP
		CLC
BSYDRDYDONE	POP AX
		POP DX
			RET
BSYDRDYTIMEOUT	STC
		JMP BSYDRDYDONE

BSYCOUNT:	DW	00H

BSYERRORSTR:	DB	'BSY ERROR',0DH,0AH,'$'


BSY		PUSH DX
		PUSH AX
		CALL DELAY
		MOV DX,[CS:STATUS]		   ;bsy clr loop1
		IN  AL,DX	
		MOV [CS:STATBYTE],AL
		CLC
		AND AL,80H
		CMP AL,00H
		JE BSYCLR
		STC
BSYCLR		POP AX
		POP DX
		RET


BSY0		PUSH DX
		PUSH AX
		MOV WORD [CS:BSYCOUNT],0
BSY0LOOP	INC WORD [CS:BSYCOUNT]
		CALL DELAY
		CMP WORD [CS:BSYCOUNT],00H
		JE BSY0TIMEOUT
		MOV DX,[CS:STATUS]		   ;bsy clr loop1
		IN  AL,DX
		MOV [CS:STATBYTE],AL
		AND AL,01H
		CMP AL,01H
		JE BSY0TIMEOUT
		MOV AL,[CS:STATBYTE]
		AND AL,080H
		CMP AL,00H
		JNE BSY0LOOP
		CLC
BSY0DONE	POP AX
		POP DX
		RET
BSY0TIMEOUT
		STC
		JMP BSY0DONE


BSY1		PUSH DX
		PUSH AX
		MOV WORD [CS:BSYCOUNT],0
BSY1LOOP	INC WORD [CS:BSYCOUNT]
		CALL DELAY
		CMP WORD [CS:BSYCOUNT],00H
		JE BSY1TIMEOUT
		MOV DX,[CS:STATUS]		   ;bsy clr loop1
		IN  AL,DX
		MOV [CS:STATBYTE],AL
		AND AL,80H
		CMP AL,80H
		JNE BSY1LOOP
		CLC
BSY1DONE	POP AX
		POP DX
		RET


BSY1TIMEOUT	PUSH DX
		MOV DX,BSYERRORSTR
		CALL PRN_DX
		POP DX
		POP AX
		POP DX
		STC
		RET


DRQCOUNT:	DW	00H

DRQ		PUSH DX
		PUSH AX
		MOV DX,[CS:STATUS]
		IN  AL,DX
		IN  AL,DX	
		MOV [CS:STATBYTE],AL
		CLC
		AND AL,08H
		CMP AL,00H
		JE DRQCLR
		STC		; DRQ SET
DRQCLR		POP AX
		POP DX
		RET		; DRQ CLR


DRQ0		PUSH DX
		PUSH AX
		MOV WORD [CS:DRQCOUNT],0
DRQ0LOOP	INC WORD [CS:DRQCOUNT]
		CALL DELAY
		CMP WORD [CS:DRQCOUNT],00H
		JE DRQ0TIMEOUT
		MOV DX,[CS:STATUS]		   ;bsy clr loop1
		IN  AL,DX
		MOV [CS:STATBYTE],AL
		AND AL,08H
		CMP AL,00H
		JNE DRQ0LOOP
		CLC
DRQ0DONE	POP AX
		POP DX
		RET

DRQ0TIMEOUT	STC
		JMP DRQ0DONE


DRQ1		PUSH DX
		PUSH AX
		MOV WORD [CS:DRQCOUNT],0
DRQ1LOOP	INC WORD [CS:DRQCOUNT]
		CALL DELAY
		CMP WORD [CS:DRQCOUNT],00H
		JE DRQ1TIMEOUT
		MOV DX,[CS:STATUS]		   ;bsy clr loop1
		IN  AL,DX
		MOV [CS:STATBYTE],AL
		AND AL,08H
		CMP AL,08H
		JNE DRQ1LOOP
		CLC
DRQ1DONE	POP AX
		POP DX
		RET
DRQ1TIMEOUT	STC
		JMP DRQ1DONE


DRDYCOUNT:	DW	00H

DRDY		PUSH DX
		PUSH AX
		MOV DX,[CS:STATUS]
		IN  AL,DX
		IN  AL,DX	
		MOV [CS:STATBYTE],AL
		CLC
		AND AL,40H
		CMP AL,00H
		JE DRDYCLR
		STC		
DRDYCLR		POP AX
		POP DX
		RET		

DRDY0		PUSH DX
		PUSH AX
		MOV WORD [CS:DRDYCOUNT],0
DRDY0LOOP	INC WORD [CS:DRDYCOUNT]
		CALL DELAY
		CMP WORD [CS:DRDYCOUNT],00H
		JE DRDY0TIMEOUT
		MOV DX,[CS:STATUS]
		IN  AL,DX
		MOV [CS:STATBYTE],AL
		AND AL,040H
		CMP AL,00H
		JNE DRDY0LOOP
		CLC
DRDY0DONE	POP AX
		POP DX
		RET
DRDY0TIMEOUT	STC
		JMP DRDY0DONE


DRDY1		PUSH DX
		PUSH AX
		MOV WORD [CS:DRDYCOUNT],0
DRDY1LOOP	INC WORD [CS:DRDYCOUNT]
		CALL DELAY
		CMP WORD [CS:DRDYCOUNT],00H
		JE DRDY1TIMEOUT
		MOV DX,[CS:STATUS]
		IN  AL,DX
		MOV [CS:STATBYTE],AL
		AND AL,040H
		CMP AL,00H
		JNE DRDY1LOOP
		CLC
DRDY1DONE	POP AX
		POP DX
		RET
DRDY1TIMEOUT	STC
		JMP DRDY1DONE

SAVEREGS	MOV [CS:OLD_AX],AX
		MOV [CS:AX_IN],AX
		MOV [CS:BX_IN],BX
		MOV [CS:CX_IN],CX
		MOV [CS:DX_IN],DX
		MOV [CS:AH_IN],AH
		MOV [CS:BH_IN],BH
		MOV [CS:CH_IN],CH
		MOV [CS:DH_IN],DH
		MOV [CS:AL_IN],AL
		MOV [CS:BL_IN],BL
		MOV [CS:CL_IN],CL
		MOV [CS:DL_IN],DL
		MOV [CS:SI_IN],SI
		MOV [CS:DI_IN],DI
		MOV [CS:BP_IN],BP
		PUSH DS
		PUSH ES
		POP AX
		MOV [CS:ES_IN],AX
		POP AX
		MOV [CS:DS_IN],AX
		MOV AX,[CS:AX_IN]
		RET

RTNREGS
		MOV AX,[CS:DS_IN]
		MOV DS,AX
		MOV AX,[CS:ES_IN]
		MOV ES,AX
		MOV AH,[CS:AH_IN]
		MOV BH,[CS:BH_IN]
		MOV CH,[CS:CH_IN]
		MOV DH,[CS:DH_IN]
		MOV AL,[CS:AL_IN]
		MOV BL,[CS:BL_IN]
		MOV CL,[CS:CL_IN]
		MOV DL,[CS:DL_IN]
		MOV SI,[CS:SI_IN]
		MOV DI,[CS:DI_IN]
		MOV BP,[CS:BP_IN]
		RET

DONESTATUS:	DB	00H
STATBYTE:	DB	020H
ERRORBYTE:	DB	030H
LOCALDRVS:      DB      00H
TOTALREMS:      DB      00H

P0BASE:	        DW	00H  ;BASE ADDRESS FOR PORT Ex: 0168H TERTIARY
P0MIRQ:         DB      0FFH ;IRQ # FOR PORT AND OR CARD

P0MDRIVE:	DB	0FFH ; BIOS DRIVE NUMBER
P0MMSTR:        DB      00H  ;00h is master ; Non 00h is slave
P0MLBA:  	DB	00H  ;00h is CHS    ; Non 00h is LBA
P0MREM:  	DB	00H  ;00h is nonremovable     ; Non 00h is removable
P0MCYL:  	DW	00H  ;COPIES TO MYCYLINDERS
P0MHEADS:	DW	00H  ;COPIES TO MYHEADS
P0MSECTORS:	DW	00H  ;COPIES TO MYSECTORS

P0SDRIVE:	DB	0FFH ; BIOS DRIVE NUMBER
P0SMSTR:        DB      00H  ;00h is master ; Non 00h is slave
P0SLBA:  	DB	00H  ;00h is CHS    ; Non 00h is LBA
P0SREM:  	DB	00H  ;00h is nonremovable     ; Non 00h is removable
P0SCYL:  	DW	00H  ;COPIES TO MYCYLINDERS
P0SHEADS:	DW	00H  ;COPIES TO MYHEADS
P0SSECTORS:	DW	00H  ;COPIES TO MYSECTORS

;NEED TO SETUP FOR CHANGING FROM MASTER TO SLAVE FOR ID SCAN. Done 6-25-01
;NEED ROUTINES FOR P0M,P0S Etc. TO TO OURDRIVE - On detect 'DL' Local
;DO WE WANT MULTIPLE PORTS SUPPORTED? - Yes!
;NEED MSLBA TO SUPPORT ISMSTR FOR MSL AND LBA. Done 6-25-01
;REMOVABLE SUPPORT NEEDS TO BE FIGURED OUT. - Good Luck.

OURDRIVE	DB	0FFH ; BIOS DRIVE NUMBER
ISMSTR:         DB      00H  ;00h is master ; Non 00h is slave
ISLBA:		DB	00H  ;00h is CHS    ; Non 00h is LBA
ISREM:		DB	00H  ;00h is nonremovable     ; Non 00h is removable
MYCYLINDERS:	DW	00H  ;Cylinders for current drive
MYHEADS:	DW	00H  ;Heads     for current drive
MYSECTORS:	DW	00H  ;Sectors   for current drive
IRQ:            DB      0FFH ;IRQ # FOR PORT AND OR CARD
BASE:		DW	BASEOFPORT+0H	
DATAREG:	DW	BASEOFPORT+0H
ERRORREG:	DW	BASEOFPORT+01H
SECTORCOUNT:	DW	BASEOFPORT+02H

SECTORNUMBER:;	DW	BASEOFPORT+03H
LBA_00_07:	DW	BASEOFPORT+03H	 ; Lba Bits 00 - 07

CYLINDERLOW:;	DW	BASEOFPORT+04H
LBA_08_0F:	DW	BASEOFPORT+04H	 ; Lba Bits 08 - 0F

CYLINDERHIGH:;	DW	BASEOFPORT+05H
LBA_10_17:	DW	BASEOFPORT+05H	 ; Lba Bits 10 - 17

DRIVEHEAD:;	DW	BASEOFPORT+06H
LBA_18_1B:	DW	BASEOFPORT+06H	 ; Lba Bits 18 - 1B

COMMAND:;	DW	BASEOFPORT+07H
STATUS:		DW	BASEOFPORT+07H

CYL_IN          DW      00H
HEAD_IN         DW      00H
SECTOR_IN       DW      00H

OLD_AX:		DW	00H
AX_IN:		DW	00H
BX_IN:		DW	00H
CX_IN:		DW	00H
DX_IN:		DW	00H
AH_IN:		DB	00H
BH_IN:		DB	00H
CH_IN:		DB	00H
DH_IN:		DB	00H
AL_IN:		DB	00H
BL_IN:		DB	00H
CL_IN:		DB	00H
DL_IN:		DB	00H
SI_IN:		DW	00H
DI_IN:		DW	00H
DS_IN:		DW	00H
ES_IN:		DW	00H
BP_IN:		DW	00H

XFERD:          DB      00H
XFERCOUNT:	DB	00H
XFERSEG:	DW	00H
XFEROFS:	DW	00H
REMPARM:        DB      0AFH,002H,025H,002H
                DB      012H,01BH,0FFH,06CH
                DB      0F6H,00FH,008H,04FH,00H

LFSTR:		DB	0DH,0AH,'$'
OLD13:		DB	'OLD INT 13 WAS AT ->$'
DRVBSY:		DB	'THE DRIVER IS BUSY ','$'
UNKNOWN:	DB	'UNKNOWN ERROR',0DH,0AH,'$'
USETHIS:	DB	0DH,0AH
		DB	'THIS IS TEST PRE-DOS BOOT CODE',0DH,0AH
		DB	'VERSION 0.63 ALPHA USE AT OUR OWN RISK',0DH,0AH
		DB	'DO YOU WANT TO USE THIS DRIVE Y/N -> ','$'
NTHR:		DB	'DEVICE OR PORT NOT PRESENT ','$'
HEXSET:		DB	'0123456789ABCDEF $'
PRNSPC:		DB	'  $'
		DB	0FFH
FUNCBUF:	RESB    0100H
		DB	0FFH
MYBUFFER:	RESW	0100H
		DB	0FFH

PRNPACKET       RET     ; This is for sanity checking for NDD
;                NOP
;                PUSH AX
;                MOV AH,[SI]
;                MOV [CS:PRNBYTE],AH
;                CALL PRN_BYTE
;                CALL SPC
;                MOV AH,[SI+01H]
;                MOV [CS:PRNBYTE],AH
;                CALL PRN_BYTE
;                CALL SPC
;                MOV AH,[SI+02H]
;                MOV [CS:PRNBYTE],AH
;                CALL PRN_BYTE
;                CALL SPC
;                MOV AH,[SI+03H]
;                MOV [CS:PRNBYTE],AH
;                CALL PRN_BYTE
;                CALL SPC
;                CALL SPC
;                MOV AX,[SI+04H]
;                MOV [CS:PRNWORD],AX
;                CALL PRN_WORD
;                CALL SPC
;                MOV AX,[SI+06H]
;                MOV [CS:PRNWORD],AX
;                CALL PRN_WORD
;                CALL SPC
;                CALL SPC
;                MOV AX,[SI+08H]
;                MOV [CS:PRNWORD],AX
;                CALL PRN_WORD
;                CALL SPC
;                MOV AX,[SI+0AH]
;                MOV [CS:PRNWORD],AX
;                CALL PRN_WORD
;                CALL SPC
;                MOV AX,[SI+0CH]
;                MOV [CS:PRNWORD],AX
;                CALL PRN_WORD
;                CALL SPC
;                MOV AX,[SI+0EH]
;                MOV [CS:PRNWORD],AX
;                CALL PRN_WORD
;                CALL SPC
;                CALL LF
;                POP AX
;                RET

