;[x] 18/12/2023. добавление/допиливание API CD-ROM (ATAPI) ;██████████████████████████████████████████████████████████████████████████ ;CD ROM DRIVE DRIVER ;--------------------------------------------------------------- ;Rev Date Name Description ;--------------------------------------------------------------- ; 02-08-2001 DNS Initial this module ;--------------------------------------------------------------- ;======================================================== ;!TODO ;!TODO ;!TODO ;!TODO ;!TODO ;!TODO ;!TODO ;!TODO ;!TODO ;!TODO ;!TODO ;!TODO ; ; [ ] установка параметра максимального размера для чтения через DRV_SET_PAR ; ;---------------------------------------------------------------------------------- MAX_ATAPI_SEC_SIZE EQU 4096/2 PACKET_SIZE EQU 12 ; !FIXIT брать из IDENTIFY PACKET DEVICE RAM_ATAPI_PK EQU SYS_PAGE.SHARED_BUFFER_32b RAM_ATAPI_RW_CMD EQU SYS_PAGE.SHARED_BUFFER_32b+16 MAX_DATA_PACKET_FOR_REQUEST_SENSE EQU 254 ASSERT ((PACKET_SIZE % 4) = 0), "PACKET_SIZE must be an even number" ;[]================================================================[#51] ;!FIXIT сделать настоящий ресет CD_5x_RESET: LD C,IDE.Device.ATAPI CALL SELECT_DRIVE RET C LD B,50 .loop: PUSH BC LD HL,ATAPI_CMD_PACKET.NOP LD DE,0 ; маркер того, что не нужно читать с устройства в ОЗУ CALL EXEC_PACKET_COMMAND ;!FIXIT ;[ ] sector size. сделать реинит HDD_INIT_TABLE POP BC RET NC ; CALL CD_CHECK_MEDIA_CHANGED RET C ; EI HALT DJNZ .loop RET ;[]================================================================[#51] ;[]================================================================[#58] ;Function: Get Current Media Parameters ; A - Disk ;Return: ; H - Heads ; L - Sectors per cylinder ; DE - Cylinders ; IX - Capacity sector in bytes ; B - Flags: MASTER/SLAVE, LBA/CHS CD_5x_GETMED: LD C,IDE.Device.ATAPI CALL SELECT_DRIVE RET C ; IN A,(SLOT3) EX AF,AF' LD A,SYS_PAGE OUT (SLOT3),A ; ; [ ] sector size. media changed CALL CD_CHECK_MEDIA_CHANGED JR NC,.get_data ; ; CP BIOS.Error.ATAPI.UnitAttention ; JR NZ,.get_data ; LD A,(IY + IDE.HDD_INIT_TABLE.RemovableMedia) AND %1111'1101 LD (IY + IDE.HDD_INIT_TABLE.RemovableMedia),A ; .get_data: ; ; LD L,(IY+IDE.HDD_INIT_TABLE.SectorsPerTrack) ; LD H,(IY+IDE.HDD_INIT_TABLE.HeadsNumber) ; LD E,(IY+IDE.HDD_INIT_TABLE.CylinderNumberLow) ; LD D,(IY+IDE.HDD_INIT_TABLE.CylinderNumberHigh) LD B,(IY+IDE.HDD_INIT_TABLE.DRV_Flags) LD L,(IY+IDE.HDD_INIT_TABLE.SectorSize) ;[ ] sector size LD H,(IY+IDE.HDD_INIT_TABLE.SectorSize + 1) ;[ ] sector size EX DE,HL LD XL,E LD XH,D ; LD HL,0 LD D,H LD E,H EX AF,AF' OUT (SLOT3),A ;AND A RET ;[]================================================================[#58] ;!TODO ; atapi.pdf стр. 24 запись/чтение могут быть максимальными блоками в несколько заходов ;[]================================================================[#55] ;Function: Read Sectors ; A - Disk ; HL:IX - Sector ; DE - Address ; B - Sector counter ;Return: ; HL:IX - Sector + Sector counter ; DE - Address + (Sector counter * Size sector) ;READ SECTOR(S) CD_5x_READ: EX AF,AF' IN A,(SLOT3) EX AF,AF' ;[]================================================================[#52] ;Function: Long Read Sectors ; A - Disk ; HL:IX - Sector ; DE - Address ; B - Sector counter ; A'- Memory Page Number ;Return: ; HL:IX - Sector + Sector counter ; DE - Address + (Sector counter * Size sector) ;LONG READ SECTOR(S) CD_5x_LONG_READ: AND A ; PUSH IY SAFE_PORTY_2 PUSH BC PUSH IX PUSH HL ; EX AF,AF' AND A ;read EX AF,AF' CALL RW_ATAPI_SECTORs ; [ ] sector size. media changed JP HDD_5x_LONG_READ.shared ; JP NC,HDD_5x_LONG_READ.shared ; CP BIOS.Error.UnitAttention ; JR Z,CD_MEDIA_CHANGED_ERROR ; SCF ;[]================================================================[#52] ; INPUT: ; A - Disk ; HL:IX - Sector ; DE - Address ; B - Sector counter ; A'- Memory Page Number ; CF'=1 - write, CF'=0 - read ; ; OUTPUT: ; RW_ATAPI_SECTORs: LD C,IDE.Device.ATAPI CALL SELECT_DRIVE RET C ; EXX LD C,SLOT3 IN B,(C) PUSH BC LD A,SYS_PAGE OUT (C),A ; [ ] media change LD A,(IY + IDE.HDD_INIT_TABLE.RemovableMedia) AND %0000'0010 JR NZ,.error_media ; LD HL,ATAPI_CMD_PACKET.READ EX AF,AF' JR NC,.read_cmd LD HL,ATAPI_CMD_PACKET.WRITE .read_cmd: EX AF,AF' LD DE,RAM_ATAPI_RW_CMD LD BC,PACKET_SIZE LDIR EXX ; LD A,H LD H,L LD L,A LD (RAM_ATAPI_RW_CMD + ATAPI_PACKET.SECTOR+0),HL LD A,XH LD (RAM_ATAPI_RW_CMD + ATAPI_PACKET.SECTOR+2),A ;R01 LD A,XL LD (RAM_ATAPI_RW_CMD + ATAPI_PACKET.SECTOR+3),A ;R01 LD A,B LD (RAM_ATAPI_RW_CMD + ATAPI_PACKET.COUNTER+1),A ;R01 ; ; EX AF,AF' ; OUT (SLOT3),A ; ; POP AF ; OUT (SLOT3),A LD HL,RAM_ATAPI_RW_CMD CALL EXEC_PACKET_COMMAND ; .exit: POP BC ;LD C,SLOT3 OUT (C),B RET ; .error_media: EXX LD A,BIOS.Error.ATAPI.UnitAttention SCF JR .exit ;[]===========================================================[#52, #55] ;[]================================================================[#56] ;Function: Write Sectors ; A - Disk ; HL:IX - Sector ; DE - Address ; B - Sector counter ;Return: ; HL:IX - Sector + Sector counter ; DE - Address + (Sector counter * Size sector) ;WRITE SECTOR(S) CD_5x_WRITE: EX AF,AF' IN A,(SLOT3) EX AF,AF' ;[]================================================================[#53] ;Function: Long Write Sectors ; A - Disk ; HL:IX - Sector ; DE - Address ; B - Sector counter ; A'- Memory Page Number ;Return: ; HL:IX - Sector + Sector counter ; DE - Address + (Sector counter * Size sector) ;WRITE SECTOR(S) CD_5x_LONG_WRITE: AND A ; PUSH IY SAFE_PORTY_2 PUSH BC PUSH IX PUSH HL ; EX AF,AF' SCF ;write EX AF,AF' CALL RW_ATAPI_SECTORs ; JP HDD_5x_LONG_READ.shared ;[]================================================================[#57] ;Function: Detect Disk ; A - Disk ;Return: CF=0 - A=Drive type ; CF=1 - drive not present, A=#02 CD_5x_DETECT: LD C,IDE.Device.ATAPI AND %1011'1111 JP DRV_DETECT ;[]================================================================[#57] ;[]================================================================[#5E] ; [ ] ;Function: Extended ; A - Disk ; B - SubFunction ;Return: ; CD_5x_Extended: LD C,IDE.Device.ATAPI CALL SELECT_DRIVE RET C ; LD A,B CP 2 JR C,TRAY_FN ; B = 0 или 1 ; JR Z,CD_REQUEST_SENSE ; B = 2 ; ... ; ... ;LD A,#AA LD A,BIOS.Error.InvalidSubFunction SCF RET ;[]================================================================[#5E] ;----------------------------------------------------------------------;!TODO сделать доступной через расширенную функцию API ; вход: DE - адрес для данных CD_REQUEST_SENSE: LD HL,ATAPI_CMD_PACKET.REQUEST_SENSE JR EXEC_PACKET_COMMAND ;----------------------------------------------------------------------; ;[ ] media changed ;----------------------------------------------------------------------; CD_CHECK_MEDIA_CHANGED: EXX LD DE,256*(IDE.CtrlByte.Error) + 0 CALL CD_WAITPRT.Custom EXX ;RET NC JR C,.noWait ; EXX LD BC,SLOT3 IN B,(C) LD A,SYS_PAGE OUT (C),A ; LD A,(IY + IDE.HDD_INIT_TABLE.RemovableMedia) OUT (C),B EXX RRA RRA LD A,BIOS.Error.ATAPI.UnitAttention RET ; .noWait: EXX CALL CD_GET_ERROR OR #70 EXX CP BIOS.Error.ATAPI.NoSence ;SCF RET NZ ; CALL CD_MEDIA_CHANGED_ERROR ; LD A,BIOS.Error.ATAPI.UnitAttention RET ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; TRAY_FN: LD HL,ATAPI_CMD_PACKET.CLOSE LD DE,0 ; маркер того, что не нужно читать с устройства в ОЗУ DEC A JR Z,EXEC_PACKET_COMMAND LD HL,ATAPI_CMD_PACKET.OPEN ;JR EXEC_PACKET_COMMAND ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; ; INPUT: HL - AP packet (12bytes) ; DE - address for/with data if needed ; ; RETURN: CF - ERROR ; !TODO CD ERRORS to INCLUDES ; #01 - RECOVERED ERROR ; #02 - NOT READY ; #03 - MEDIUM ERROR ; #04 - HARDWARE ERROR ; #05 - ILLEGAL REQUEST ; #06 - UNIT ATTETION ; #07 - DATA PROTECT ; #0B - ABORTED COMMAND ; #80 - TIME OUT EXEC_PACKET_COMMAND: EXX CALL CD_WAITPRT EXX JR NC,.READY ; ; [ ] media changed ; CP +(BIOS.Error.UnitAttention & #0F) ; JR NZ,.reset ; ; ; CALL CD_MEDIA_CHANGED_ERROR ; OR #70 ; error prefix for ATAPI in BIOS ; SCF ; RET ; .reset: LD BC,IDE.Write.Command LD A,IDE.ATAPI.Reset OUT (C),A ; LD B,#80 .pause: DJNZ .pause ; EXX CALL CD_WAITPRT EXX ;RET C JR C,CD_CHECK_MEDIA_CHANGED.noWait ; .READY: LD C,SLOT3 IN B,(C) PUSH DE PUSH BC ; LD A,SYS_PAGE OUT (C),A LD DE,RAM_ATAPI_PK ;!FIXIT может на стеке выделять место? LD BC,PACKET_SIZE LDIR ; POP BC POP DE OUT (C),B ; XOR A EXX ;OUT (C),A ;XOR A LD BC,IDE.Write.Features OUT (C),A LD DE,MAX_ATAPI_SEC_SIZE ;SIZE BLOCK ;!HARDCODE доставать из переменной какой-нибудь LD BC,IDE.Write.ByteCountLow OUT (C),E LD BC,IDE.Write.ByteCountHigh OUT (C),D LD BC,IDE.Write.Command LD A,IDE.ATAPI.Packet OUT (C),A CALL CD_WAITPRT EXX ;RET C JR C,CD_CHECK_MEDIA_CHANGED.noWait ; EXX LD DE,256*(IDE.CtrlByte.DataRequest+IDE.CtrlByte.Error)+IDE.CtrlByte.DataRequest CALL CD_WAITPRT.Custom EXX BIT IDE.CtrlBit.Error,A JR NZ,CD_CHECK_MEDIA_CHANGED.noWait JR NC,.YEP_DRQ LD A,BIOS.Error.ATAPI.TimeOut ;!FIXIT media change test RET ; ; .CMD_ERROR: CALL CD_GET_ERROR ; OR #70 ; CP BIOS.Error.UnitAttention ; CALL Z,CD_MEDIA_CHANGED_ERROR ; ;LD BC,IDE.Read.Error ;ERROR ; ;IN A,(C) ; ;RRCA ; ;RRCA ; ;RRCA ; ;RRCA ; ;AND #0F ; ;!FIXIT ; [ ] sector size. make REQUEST SENSE if A=6 ; SCF ; RET ; EXEC ATAPI PACKET COMMAND .YEP_DRQ: LD C,SLOT3 IN B,(C) PUSH BC LD A,SYS_PAGE OUT (SLOT3),A LD HL,RAM_ATAPI_PK LD BC,IDE.Write.Data LD A,PACKET_SIZE/4 ; !FIXIT брать из IDENTIFY PACKET DEVICE .OUTPKT: OUTI OUTI OUTI OUTI DEC A JR NZ,.OUTPKT ; POP BC OUT (C),B ; LD B,#80 .pause2: DJNZ .pause2 ; EX AF,AF' LD XH,A ; страница для R/W_LONG LD XL,0 EX AF,AF' ; EX DE,HL .AP_LOOP: EX DE,HL IN A,(SLOT3) EX AF,AF' ;>-----------> \ ; EXX CALL CD_WAITPRT EXX RET C LD BC,IDE.Read.Status IN A,(C) BIT IDE.CtrlBit.Error,A JP NZ,CD_CHECK_MEDIA_CHANGED.noWait ; AND IDE.CtrlByte.DataRequest RET Z ;NO DATA REQUEST. A = 0: BIOS.Error.NoErrors ; LD A,XH OUT (SLOT3),A ; ;====== IF DATA REQUEST =======================================; ; EX DE,HL LD BC,IDE.Read.ByteCountLow IN E,(C) LD BC,IDE.Read.ByteCountHigh IN D,(C) ;TRANSFER BLOCK SIZE LD A,D OR E RET Z ;BLOCK = 0 ; LD BC,IDE.Read.InterruptReason IN A,(C) AND IDE.InterruptReasonByte.IO LD BC,IDE.Read.Data JR Z,.WRITE_DATA ; ;READ .read_loop: INI INI DEC DE DEC DE LD A,D OR E JR NZ,.read_loop ; .return_rw: INC XL ;INC LOADED SECTORS EX AF,AF' ;<-----------< / OUT (SLOT3),A ; LD A,H OR L JR NZ,.AP_LOOP ; next page in mem block LD HL,#C000 IN A,(SLOT3) EX AF,AF' ;>-----------> \ LD A,SYS_PAGE OUT (SLOT3),A LD D,high SYS_PAGE.RAM_TABLE LD E,XH LD A,(DE) LD XH,A EX AF,AF' ;<-----------< / OUT (SLOT3),A JR .AP_LOOP ; ; ;WRITE .WRITE_DATA: INC B ; LD BC,IDE.Write.Data .write_loop: OUTI OUTI DEC DE DEC DE LD A,D OR E JR NZ,.write_loop JR .return_rw ;.NULL: LD BC,IDE.Read.Data ;.RD_N_CD: IN A,(C) ; DEC B ; IN A,(C) ; DEC B ; DEC DE ; DEC DE ; LD A,D ; OR E ; JR NZ,.RD_N_CD ; ; DE = 0 ; JR .AP_LOOP ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; CD_GET_ERROR: LD BC,IDE.Read.Error ;ERROR IN A,(C) RRCA RRCA RRCA RRCA AND #0F RET ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; ; D - MASK, E - PATTERN CD_WAITPRT: LD DE,256*(IDE.CtrlByte.Busy) + 0 .Custom: LD B,100 LD HL,#0000 .LOOP: LD A,high IDE.Read.Status IN A,(low IDE.Read.Status) CP #FF JR Z,.error AND D CP E ; RET Z ; .NEXT_TRY: DEC L JR NZ,.LOOP DEC H JR NZ,.LOOP DJNZ .LOOP ; ;EX AF,AF' .error: ; !FIXIT error number SCF RET ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; ; CD_TEST: LD HL,ATAPI_CMD_PACKET.NOP ; LD DE,0 ; маркер того, что не нужно читать с устройства в ОЗУ ; JP EXEC_PACKET_COMMAND ;----------------------------------------------------------------------; ;----------------------------------------------------------------------; CD_MEDIA_CHANGED_ERROR: IN A,(SLOT3) PUSH AF LD A,SYS_PAGE OUT (SLOT3),A ; LD DE,SYS_PAGE.SHARED_BUFFER_256b CALL CD_REQUEST_SENSE ; LD A,(SYS_PAGE.SHARED_BUFFER_256b + 2) ; SenceKey. 06 CP 6 JR NZ,.exit ; LD A,(SYS_PAGE.SHARED_BUFFER_256b + 12) ; AdditionalSenceKey. #28 CP #28 JR NZ,.exit ; LD A,(SYS_PAGE.SHARED_BUFFER_256b + 13) ; AdditionalSenseCodeQualifier. 0 AND A JR NZ,.exit ; LD A,(IY + IDE.HDD_INIT_TABLE.RemovableMedia) OR %0000'0011 LD (IY + IDE.HDD_INIT_TABLE.RemovableMedia),A ; LD HL,ATAPI_CMD_PACKET.READ_CAPACITY_DATA LD DE,SYS_PAGE.TMP_BUFFER CALL EXEC_PACKET_COMMAND LD HL,#FFFF JR C,.No_Media ; LD HL,(SYS_PAGE.TMP_BUFFER + 6) ; sector size (high byte, low byte) ; .No_Media: LD (IY+IDE.HDD_INIT_TABLE.SectorSize),H ;[ ] sector size LD (IY+IDE.HDD_INIT_TABLE.SectorSize + 1),L ; POP AF OUT (SLOT3),A LD A,BIOS.Error.ATAPI.UnitAttention SCF RET ; .exit: POP AF OUT (SLOT3),A ; CF=0 ;AND A RET ;----------------------------------------------------------------------; //////////////////////////////////////////////////////////////////////// ATAPI_CMD_PACKET: .NOP: DUP 12 DB #00 EDUP ; .OPEN: DB #1B DB #00,#00,#00 DB #02 DB #00,#00,#00,#00,#00,#00,#00 ; .CLOSE: DB #1B DB #00,#00,#00 DB #03 DB #00,#00,#00,#00,#00,#00,#00 ; .READ: DB #28,#00 DB #00,#00,#00,#00 ; sector dword DB #00 DB #00,#01,#00,#00 ; counter dword DB #00 ; .WRITE: DB #2E,#00 DB #00,#00,#00,#00 ; sector dword DB #00 DB #00,#01,#00,#00 ; counter dword DB #00 ; .READ_CAPACITY_DATA: DB #25 BLOCK 11,0 ; .REQUEST_SENSE: DB #03 DB #00,#00,#00 DB MAX_DATA_PACKET_FOR_REQUEST_SENSE DB #00,#00,#00,#00,#00,#00,#00 ; ATAPI_PACKET: .SECTOR EQU 2 .COUNTER EQU 7 //////////////////////////////////////////////////////////////////////// ; ; E - Second * 10 ; PAUSE LD HL,#0000 ; PAUSE1 DEC L ; JR NZ,PAUSE1 ; DEC H ; JR NZ,PAUSE1 ; DEC E ; JR NZ,PAUSE1 ; RET ; /* Если ловится ошибка media changed, то биос должен выставлять в HDD_INIT_TABLE.RemovableMedia = 3 и затирать FF SectorSize. Дос после получения такой ошибки должен вызывать BIOS.DRV_DETECT и если всё ОК, то ReScanDRV */