; NOVAXIS Turbo-R SCSI BIOS version 1.0 ; (C) 1994 KMcs ; Written by Jurgen Kramer - 05/05/94 - ; - 06/05/94 - ; - 15/05/94 - ; - 20/05/94 - ; - 23/05/94 - ; - 26/05/94 - V1.02 ; - 27/05/94 - Adding new CALL command SETHOSTID (variable) ; - 01/06/94 - ; - 04/06/94 - Extended NOVAXIS JUMP table ; - 13/06/94 - ; - 15/06/94 - ; - 16/06/94 - NOVAXIS Turbo-R/MSX version 0.01 ; - 17/06/94 - Added part between *M* 2* ; - 20/06/94 - NOVAXIS Turbo-R/MSX version 0.02 ; Target ID is software setable (0 - 3) stored in clockchip ; - 23/06/94 - version 0.03 - Added GetHOST_ID, fixed bug for HOST ID ; - 28/06/94 - Setup/Diag updated ; - 06/07/94 - ; - 25/07/94 - v0.05 ; - 02/08/94 - ; - 03/08/94 - ; - 04/08/94 - ; - 07/08/94 - v0.06 ; - 08/08/94 - v0.10 ; - 26/08/94 - V9990 call statements deleted ; - 27/08/94 - v0.20 Temporary test routines added ; - 28/08/94 - v0.21 GetInq routine modified because of errors in BASIC ; - 02/09/94 - v0.30 Temporary other TermAct and SetWD3393 ; - 04/09/94 - v0.31 Added Multiple HDD support switch ; - 07/09/94 - v0.32 SBIC error msg changed, Controller test and SCSI bus ; test switched ; - 11/09/94 - v0.40 CALL statement routine modified ; - 21/09/94 - v0.41 original TermAct & SetWD3393 restored ; - 25/09/94 - Bug removed in GetInq routine ; - 27/09/94 - v0.42 GetInq modified, revision added ; - 28/09/94 - v0.43 TermAct replaced ; - 07/10/94 - v0.44 _SETHOSTID modified ; - 08/10/94 - v0.45 Get_ID, SetHTID modified, HOST ID now only occupies 3 ; bits in the clockchip instead of 4 ; - 09/10/94 - v0.46 _INQUIRY added ; - 12/10/94 - ; - 16/10/94 - v0.47 Temporary test routines deleted ; - 19/10/94 - v0.48 GetSense added, bug removed in PrInitTxt ; - 28/10/94 - v0.49 GetUnitsOn routine modified ; - 30/10/94 - v0.50 Temporary stuff added for test purpose ; Changed name of routine SetWD33C93 in SetWD3393 ; - 03/11/94 - ; - 13/11/94 - TermAct modified because of a bug in the SCSI controller chip ; - v0.60 Beta Release 1, v0.50 test functions disabled ; - 22/11/94 - v0.61 Added RdDefect routine ; - 29/11/94 - Preparing for final version, deleted some temporary routines ; 'finished' Setup ; v1.00 !! version for export to Japan ; - 17/12/94 - v1.01 Removed ExtSetWD33C93 routine, added new comments to ; some routines, modified SetWD3393 routine ; - 23/12/94 - Testing new SCSI read routine ; - 28/12/94 - v1.02 DSKIO modified, now also recognizes 0f8h as media id. ; this is implemented for use with a IBM compatible PC which ; uses 0f0h as media id. But this media is also used for MSX ; SSDD diskettes! ; - 28/12/94 - v1.03 SCSI COPY command added for high end applications. ; - 02/01/95 - v1.04 Work Area expanded to store data of new driver functions ; - 03/01/95 - Started with NExtBIOS (NOVAXIS Extended BIOS) mechanism ; - 12/01/95 - continued with NExtBIOS ; - 13/01/95 - InsNExt routine extended ; - 15/01/95 - New toggle added for use of driver support, Setup menu ; modified. ; If Driver Support is disabled, the extra memory needed for the drivers will ; not be allocated ; - 16/01/95 - Complete new screen layout for Setup menu ; - 19/01/95 - 'help' texts added to Setup menu ; - 20/01/95 - New toggle added to Setup menu for Extended Partition ; The HOST ID now only occupies 2 bits instead of 3, modified SetHOST_ID and ; Get_ID ; - 21/01/95 - v1.05Beta, small beta release. DRV_SIZE set to 1024 ; Beta testers: J. Botman, G. de Boom, R. Muit ; - 22/01/95 - v1.06 Again _INQUIRY added ; - 23/01/95 - Work Area now initialy filled with 00h instead of 0ffh ; continued with _INQUIRY command, found a small 'bug' in FastExec, is you ; use a transfer address that is just one byte higher than the transfer address ; it will still use the sectorbuffer to store the temporary ML code to read/ ; write which means if you're using the sectorbuffer to store data/code it ; will be overwritten! ; Modified Get_Inq ; - 24/01/95 - Updated CALL INFO command, at system setup the Driver support ; toggle is copied to the Work Area byte 7, bit 2. Modified InsWork, InsNExt ; Fast RAM transfer toggle removed, ChkDrvS removed ; Finished Extended Partitions toggle in Setup menu ; - 25/01/95 - Finished GetDWA ; - 26/02/95 - Made some changes in Setup menu ; - 28/02/95 - v1.07 Timeout in RdHDDPart changed to 560ms for slow devices ; like CD-ROM ; After the hardware reset (out (36h),1) it takes a very long time for the ; CD-ROM (my CD-ROM) to recover, and is therefore not printed during setup ; - 01/02/95 - Removed one space from the string Stripe, Timeout in RdHDDPart ; reset to it's original value ; Continued developing driver functions (modified DSKIO) ; - 02/03/95 - ; - 18/03/95 - Removed some redunant code ; - 19/03/95 - v1.08 Enlarged Extended Partitions Work Area to 256 bytes, ; Removed initial hardware reset by software reset ; - 24/03/95 - GetInq routine modified ; PrInitTxt modified, ROM revision level added, if the revision level equals ; 00h, it will not be displayed. PrintPBCD added ; - 26/03/95 - Rev. 04 - Continued with modifieing RdHDDPart, so it will ; display CD-ROM devices during initial setup ; - 30/03/95 - CD-ROM is still not printed sometimes...temporarily fixed with ; software loops ; - 31/03/95 - v1.09.01 ; - 01/04/95 - ; - 03/04/95 - v1.09.02 - Temporary restored old routines to convert partition ; sector ; - v1.09.03 - MedRemoval added, SCSI PREVENT ALLOW MEDIUM REMOVAL ; - v1.09.04 - Modified Write ID checking, so it's easy to update to the new ; Read/Write byte from the Extended Partitions ; - 05/04/95 - Extended partition Write checking is working ; - 06/04/95 - Changed date presentation in initial screen, now it displays ; the date as follows: March 6th, 1995. So there is not confusion about the ; date format. ; - 10/04/95 - v1.10.01 - Started with adding new MS-DOS compatible Extended ; partitions ; v1.11.01 - Organized the program a bit, RdSecDir renamed to RdLogBlk and ; WrSecDir renamed to WrLogBlk, _TEST removed ; v1.11.02 - Made InsPCTab, installs PC partitions, Network write ID is the ; same as Host ID ; v1.11.05 - Made InsMSXTab, installs MSX partitions, Network write ID is ; same as Write ID on partition sector ; v1.11.06 - Made InsNOVTab, installs Extended partitions, Network Write ID ; is set according to write ID on partition sector ; v1.11.07 - Changed GetInq routine, now the Inquiry for all SCSI device ; types is printed, not only device type 0, device type other then 0 will not ; be installed ; v1.11.08 - Modified InsMSXTab, InsPCTab and InsNOVTab to check for the ; right partition type, so 16-bit FAT part. will not be installed ; v1.11.16 - Now all devices are printed, even if there is no log. drive left ; to install. ; v1.11.17 - 26/04/95, Modified InsNOVTab to check if the Extended Partitions ; are enabled ; v1.11.22 - Removed a bug from Rd_Cnv_Prt, when Extended partitions are used ; and the was no 'Drv' found 01f3h in the part. table, IX was not proparly ; loaded ; v1.11.27 - 28/04/95, Added RdPartSecs routine to RdHDDPart, reads partition ; sectors, and when needed retries when a error occurs ; v1.12.01 - 07/05/95, NExtBIOS modified, now it does not destroy IX when ; calling EXTBIO, NExtBIOS version 0.11 ; v1.13.01 - 14/05/95, Preparing for 'final' version, Driver routine develop- ; ment temporary discontinued because of a dead-line, calls to DrvRdBlk and ; DrvWrBlk removed from DSKIO routine ; ** IMPORTANT ** further development of the ROM should be done with ; version 1.12.01, this version cannot be used because the NExtBIOS routines ; are removed ** ; InsNExt, ChkDrv, DrvRdBlk, DrvRdBlk, SuppDrv and GetDWA removed, CalcWA_1 ; and CalcWA_3 modified ; Driver support toggle removed from Setup ; v1.13.02 - Added a security string to some routines so a NOVAXIS ROM can ; always be recognized (I hope) ; v1.13.03 - 16/05/95 - ; v1.13.04 - 17/05/95 - ; v1.49.01 - 19/05/95 - Final Beta version ; v1.49.02 - 20/05/95 - Bug removed from InsNOVTab ; v1.49.07 - 21/05/95 - Spell error removed from DevTxt ; v1.49.20 - 29/05/95 - Add two CALL commands, 'TARGETID' and 'SETTARGETID' ; v1.49.21 - 30/05/95 - I/O base address message removed ; ** FINAL VERSION 1.50 ** ; I/O port 1ch ; v1.50 - 30/05/95 - ; v1.50 - 05/06/95 - Added small delay after printing all connected devices, ; Init text changed: 'MSX' extended to 'MSX2' ; *T*vX.XX marks the beginning of a temporary part of code, where X is the ; version number of NOVAXIS ; *T* marks the end ; *N*vX.XX marks the start of a newly added part ; *N* end mark .comment * NOVAXIS Turbo-R/MSX version 1.06 highlights: - Pressing GRAPH key will prevent SCSI BIOS to be installed - Pressing CTRL key will - First HDD can have ID 0-3 - Multiple HDD support (max 7) - data transfer approx. 248Kb/s (IBM, tested on Turbo-R) - approx. 100Kb/s on a MSX2/2+ - new calls commands: - HOSTID - get Host ID in variable - SETHOSTID - set Host ID _ INQUIRY - get INQUIRY of specified Target New JUMP entries for SCSI DIAGNOSTIC Address: 07FB6h - Reserved 07FB9h - Reserved 07FBCh - Copy - SCSI COPY 07FBFh - RdDefect - Read Defect Data 07FC2h - GETWRK, Get work area in [IX] 07FC5h - PartInfo, Get work area of current drive [IX] 07FC8h - GetUnitsOn - Get # of units online 07FCBh - SetHOST_ID - Set HOST ID (4-7) 07FCEh - SetTargetID (0 - 3) 07FD1h - GetTargetID (0 - 3) 07FD4h - GetHOST_ID - Get HOST ID (4-7) 07FD7h - GetSense - Get Sense info 07FDAh - MedRemove - Prevent Allow Medium Removal Clockchip block 2 nibble 12, bits 1 - 0 are used for storage of HOST ID " " 2 nibble 3 bits 3 and 2 are used to set TARGET ID (0 - 3) " " 2 nibble 11 bit 2 is used to store Multiple HDD support " " 2 nibble 11 bit 3 is used to store Driver Support " " 2 nibble 12 bit 2 is used to store Extended Partitions " " 2 nibble 12, bit 3 is AVAILABLE NOVAXIS clock-chip memory layout: Block 2 nibble | B3 | B2 | B1 | B0 | +------------------------------------+ 0 | MSX | +------------------------------------+ 1 | MSX | +------------------------------------+ 2 | MSX | +------------------------------------+ 3 | Target ID | MSX | +------------------------------------+ 4 | MSX | +------------------------------------+ 5 | MSX | +------------------------------------+ 6 | MSX | +------------------------------------+ 7 | MSX | +------------------------------------+ 8 | MSX | +------------------------------------+ 9 | MSX | +------------------------------------+ 10 | MSX | +------------------------------------+ 11 | DrvSup | MulHDD | MSX | +------------------------------------+ 12 | AVAILA | ExtPrt | HOST ID | -------------------------------------- Nibbles filled with 'MSX' are used by MSX BIOS Nibble 12 normaly contains Native code * ; Assemble with M80 .Z80 ; calbas equ 0159h ; ; BASIC interpreter routines ; rom_error equ 406fh ; 'xxxx error' rom_chrgtr equ 4666h ; get next character from text rom_frmevl equ 4c64h ; evaluate an expression (general purpose) rom_docnvf equ 517ah ; type conversion rom_getin2 equ 520fh ; get an integer (-32768..32767) to DE rom_getbyt equ 521ch ; get a byte (0..255) to A and E rom_frmqnt equ 542fh ; get an integer (-32768..65535) to DE rom_ptrget equ 5ea4h ; get a pointer to variable to DE rom_strini equ 6627h ; make a room in string space rom_frestr equ 67d0h ; get a pointer to string ; ; Work area ; buf equ 0f55eh ; line input buffer (used as a temp) valtyp equ 0f663h ; value type dsctmp equ 0f698h ; string descriptor temp dac equ 0f7f6h ; decimal accumulator ; ; Macros ; synchk macro token call synchr defb token endm chrget macro call chrgtr endm POSIT EQU 0C6h CHGET EQU 09Fh CALSLT EQU 001CH ENASLT EQU 0024H BASVER EQU 002DH WRTVDP equ 0047h INITXT EQU 006CH SNSMAT EQU 0141H KILBUF equ 0156h EXTROM EQU 015FH LINL40 equ 0f3aeh CHGMOD equ 005fh ERAFNK equ 00cch fdscr EQU 0185H ; Restore screen with clockchip parameters NSTWRT equ 0171h RDPRIM equ 0f365h ; Read primairy slot CTRL EQU 0F33FH ; Byte to keep CTRL key (no use at all) RAMAD1 EQU 0F342H $SECBUF EQU 0F34DH MEMSIZ EQU 0F672H STKTOP EQU 0F674H AUTLIN EQU 0F6ABH ; Temporary storage SAVSTK EQU 0F6B1H FILTAB EQU 0F860H NULBUF EQU 0F862H CMASK EQU 0F92CH ; Used to store CPU mode EXBRSA EQU 0FAF8H BOTTOM EQU 0FC48H HIMEM EQU 0FC4AH EXPTBL EQU 0FCC1H SLTWRK EQU 0FD09H PROCNM EQU 0FD89H DEVICE EQU 0FD99H HOKVLD equ 0fb20h EXTBIO EQU 0FFCAH ; Extended BIOS call RG12SV equ 0ffebh RG13SV equ 0ffech DCOMPR equ 0020h ; RST 20H - compare HL and DE OUTDO equ 0018h ; RST 18H - print character ; CR equ 0dh ; Carriage Return LF equ 0ah ; Line Feed ESC equ 27 ; ESCAPE ; DRV_SIZE equ 1024 ; Size of Work Area for driver management DRVENTRY equ 32 ; Size of driver entry EXT_SIZE equ 256 ; Size of Work Area for Extended partitions NRM_SIZE equ 48 ; Size of normal Work Area ; PSecBuf equ 8400h ; Sectorbuffer address (1024 bytes) TmpPDat equ 8800h ; Temporary buffer for transforming part. LogDrv equ 83fah ; # of log. drives installed WrkSav equ 83fbh ; Work Area address save TrgID equ 83fdh ; Target ID NrParts equ 83feh ; Number of partitions found TabType equ 83ffh ; Partition type DrMAPDat equ 83f2h ; Drive MAP data DiffDrv equ 83f1h ; Used to calc. number of installed drives MaxRet equ 83f0h ; Max. # of retries in RdPartSecs maxdrv equ 6 ; Max. supported log. drives ; XYpos equ 81fdh ; Cursor position for printing device info TrgID2 equ 81ffh ; Target ID for GetInq TrgStt equ 81fch ; Target status for GetInq ; controller I/O port definition baseport equ 1ch ; Base I/O port AUXSTAT equ baseport+0 ; Auxiliary Status Read REGSET equ baseport+0 ; Register set RDWREG equ baseport+1 ; Read / Write data of selected register HARDWR equ baseport+2 ; Hardware Reset WD33C93A ; Version # VERSION equ 0150h ; BCD version #, 1.50 ; ROM revision level ROMREVISION equ 0h ; Revision 0 ; default SCSI HOST ID HOSTID equ 0b0h ; B0h = 7, B1h = 6, B2h = 5 etc. ; SCSI commands - Direct Access - group 0 FORMAT equ 04h ; Format Unit READ equ 08h ; Read WRITE equ 0Ah ; Write MODSEL equ 15h ; Mode Select MODSNS equ 01ah ; Mode Sense STSTOP equ 01bh ; Start / Stop Unit MEDREM equ 01eh ; Prevent Allow Medium Removal ; SCSI commands - Direct Access - group 1 RDCAPAC equ 025h ; Read Capacity _VERIFY equ 02fh ; Verify RDEFDAT equ 037h ; Read Defect Data ; SCSI commands - All Peripheral Device Types - group 0 TSTUNRD equ 00h ; Test Unit Ready REQSENS equ 03h ; Request Sense INQUIR equ 12h ; Inquiry COPY_ equ 18h ; Copy SENDIAG equ 01dh ; Send Diagnostic ; commands for WD3393A SCSI controller ; ! indicates negative logic AssertATN equ 02h ; Assert ATN NegateACK equ 03h ; Negate ACK SelATNTrn equ 08h ; Select-with-!ATN and-Transfer TranAdd equ 18h ; Translate address TransInfo equ 20h ; Transfer Info ; .phase 4000h defm 'AB' ; ID defw INIT ; Init routine defw STTMNT ; Call statements defw 0 ; No device defw 0 ; No text defw 0,0,0 ; Reserved ; 4010h - start of diskrom jump table JP DSKIO ; DISKIO - read/write sectors ; 4013h - Check if disk is changed JP DSKCHG ; 4016h - Get DPB (Disk Parameter Block) JP GETDPB ; 4019h - JP CHOICE ; Get address of format text ; 401Ch - JP DSKFMT ; FORMAT ; 401Fh - STPDRV (stop all drives of current DISKROM) JP STPDRV ; 4022h - JP NotSupp ; BASENT - entry to start BASIC ; 4025h - (Execute FORMAT routine) NOP JP NotSupp ; 4029h - Shutdown - stop disk motor (of all connected DISKROMs) JP NotSupp ; Not supported ; 402Ch - NOP JP WHEREAMI ; WHEREAMI - Get current slot ID of page 1 ; Input : - ; Output: A = slot ID current page 1 ; Modify: WHEREAMI: CALL CalcExp ; OR (HL) ; Expanded slot? RET P ; No ; LD C,A ; Save primairy slot INC HL INC HL INC HL INC HL LD A,(HL) ; Read contents of SLTTBL AND 0Ch OR C ; Form slot address RET ; GETWRK - Get Work Area - Get base address of work area in [IX] and [HL] ; ; Work area: 6 * 8 bytes (six entries of eight bytes for each drive) ; ; Entry: ; +00 - PxxFXTAR ; + ++ +++---- Target ID ; | |+-------- Normaly 1, can be reset after DSKIO (???) ; | +-------- Formatted, 1 = partition not (MSX) formatted ; +------------ Partition enable, 1 = enable (in use) ; +01 - 03 - First sector of partition ; +04 - 05 - Number of sectors in partition ; +06 - WxxxxNNN ; + +++----- Network write ID ; +------------ Write protect partition, 0 = protected ; +07 - NxxxEDHM ; | |||+-- MSX type, 0 = normal MSX (2/2+), 1 is Turbo-R ; | ||+--- Multiple HDD support, 1 = on ; | |+---- Driver support, 1 = on ; | +----- Extended partitions, 1 = on (not supported yet) ; +--------- NExtBIOS, 1 = installed ; ; byte 7 is only filled in the first entry, in all other entries this byte ; is zero GETWRK: CALL GetSLTWRK LD A,(HL) INC HL LD H,(HL) LD L,A PUSH HL POP IX RET ; GetSLTWRK: CALL CalcExp ; ADD A,A ADD A,A ADD A,A SCF ADC A,A LD C,A LD A,(HL) ADD A,A SBC A,A AND 0CH INC HL INC HL INC HL INC HL AND (HL) OR C ADD A,A LD HL,SLTWRK JR J$40D1 ; CalcExp: CALL RDPRIM ; Read primairy slot register RRCA RRCA AND 00000011b LD HL,EXPTBL ; See if slot is expanded or not LD B,0 J$40D1: LD C,A ADD HL,BC RET ; ; Text handlers ; synchr: ld a,(hl) ; get text ex (sp),hl cp (hl) ; compare with correct token inc hl ex (sp),hl jr nz,snerr ; no match, error chrgtr: ld ix,rom_chrgtr call calbas ei ret ; ; Error handlers ; errsn equ 2 ; syntax error errfc equ 5 ; illegal function call errom equ 7 ; out of memory errtm equ 13 ; type mismatch errdio equ 19 ; device I/O error ; ** SECURITY DUMMY defb 'K' xor 'c' defb 'M' xor 's' defb 'c' xor 'K' defb 's' xor 'M' ld e,12 defb 1 ; ** dioerr: ld e,errdio defb 1 tmerr: ld e,errtm defb 1 fcerr: ld e,errfc defb 1 snerr: ld e,errsn diverr: ld ix,rom_error jr jcalbas ; ; Interface routines between ROM BASIC routines ; strini: ld ix,rom_strini jr jcalbas ptrget: ld ix,rom_ptrget jr jcalbas docnvf: ld ix,rom_docnvf jr jcalbas frmevl: ld ix,rom_frmevl jr jcalbas frestr: ld ix,rom_frestr jr jcalbas getbyt: ld ix,rom_getbyt jcalbas: call calbas ; call ROM routines ei ret ; ; Return value (integer only) to variable specified ; ; Entry: HL = pointer to variable (returned from PTRGET) ; VALTYP = type of variable ; DAC+2 = integer value to be returned ; ; Destroyes all registers ; ret_number: push hl ; save pointer to variable ld hl,valtyp ; get variable type ld a,(hl) ld c,a ; set it as length of data (2,4,8) ld (hl),2 ; set integer type ld hl,dac+2 ; assume integer cp 2 ; is it integer ? jr z,numint ; yes, just copy and done cp 4 ; is it single real ? jr z,numflt ; yes cp 8 ; is it double real ? jp nz,tmerr ; no, cannot return a value to string numflt: push bc ; save length of data call docnvf ; coerce to desired type pop bc ; restore length of data ld hl,dac ; prepare to transfer value to variable numint: ld b,0 pop de ; restore pointer to variable ldir ; store to variable ret ; ; assign a string to a variable ; ; Entry: A = length of string ; HL = pointer to variable (returned from PTRGET) ; BUF = string itself ; ; Destroyes all registers ; ret_string: push hl ; save pointer to variable push af ; save length of string call strini ld de,(dsctmp+1) ld hl,buf pop af ; restore length of string and a ; null string? jr z,ret_null ; yes ld c,a ld b,0 ldir ret_null: pop de ; restore pointer to variable ld hl,dsctmp ld bc,3 ldir ret ; *************** CALL STATEMENTS *************** ; Execute CALL SLOW statement _SLOW: LD A,80H JR J.40DE ; Execute CALL MEDIUM statement _MEDIUM: LD A,81H JR J.40DE ; Execute CALL FAST statement _FAST: LD A,82H J.40DE: PUSH AF LD A,(0180h) ; Check if BIOS is enabled CP 0C3H ; CHGCPU call available? JR Z,J$40E9 ; Yes ; POP AF ; No AND A RET J$40E9: POP AF PUSH IX PUSH IY CALL 0180h ; Change CPU mode ; POP IY POP IX AND A RET ; Execute CALL MAP2 statement _MAP2: DI PUSH HL LD HL,0C000h LD BC,03FFCh J.40FF: LD A,3AH CPIR JR NZ,J.4122 ; INC HL LD A,(HL) CP 0F2H JR NZ,J.40FF ; DEC HL LD A,(HL) CP 0C8H JR C,J.40FF ; CP 0CBH JR NC,J.40FF ; DEC HL LD (HL),0DBH INC HL LD A,(HL) ADD A,35H LD (HL),A INC HL LD (HL),00H JR J.40FF J.4122: AND A POP HL EI RET ; Execute CALL MAP statement (MAP 1) ; Fix DOS2 memory map routine _MAP: DI PUSH HL LD HL,0C000h LD BC,03FFCh J.412E: LD A,3AH CPIR JR NZ,J.4122 ; INC HL LD A,(HL) CP 0F2H JR NZ,J.412E ; DEC HL LD A,(HL) CP 0C7H JR C,J.412E ; CP 0CBH JR NC,J.412E ; DEC HL LD (HL),0DBH INC HL LD A,(HL) ADD A,35H LD (HL),A INC HL LD (HL),00H JR J.412E ; Execute CALL INFO statement _INFO: PUSH HL ; Save text pointer CALL PRINT ; DEFM 'Available CALL statements:',CR,LF,CR,LF DEFM 'CALL INFO Shows this text',CR,LF DEFM 'CALL SLOW Z80 mode.',CR,LF DEFM 'CALL MEDIUM R800 ROM mode.',CR,LF DEFM 'CALL FAST R800 RAM mode.',CR,LF DEFM 'CALL MAP Fix DOS2 mapper routine',CR,LF DEFM 'CALL MAP2 ditto - version 2',CR,LF defm 'CALL HOSTID(variable) Get SCSI Host ID',CR,LF defm 'CALL SETHOSTID(var.) Set SCSI Host ID',CR,LF defm 'CALL TARGETID(variable) Get SCSI Target ID',CR,LF defm 'CALL SETTARGETID(var.) Set SCSI Target ID',CR,LF defm 'CALL INQUIRY(var,str,str,str) Get INQUIRY of specified' defm ' Target',CR,LF,CR,LF,0 POP HL ; Restore text pointer AND A RET ; Execute CALL HOSTID command ; Syntax: _HOSTID (variable) _HOSTID: synchk '(' call ptrget ; get a pointer to variable push de ; save a pointer to variable ld a,(valtyp) push af ; save the type of variable call Get_ID cpl and 7 ld (dac+2),a xor a ld (dac+3),a pop af ; restore type of variable ld (valtyp),a ; set it to VALTYP ex (sp),hl ; save text pointer ; restore pointer to variable call ret_number pop hl ; restore text pointer synchk ')' ret ; Execute CALL SETHOSTID command ; Syntax: _SETHOSTID (x) ; x can be: - integer, singel precision, double precision ; - numeric value ; - expression _SETHOSTID: call getbyt ; Evaluate expression to a byte cp 4 ; < 4 ? jp c,fcerr ; Yes, print illegal function call cp 8 ; > 7 ? jp nc,fcerr ; Yes call ROM_SetHost ; Set HOST ID and a ; Clear CY ret ; Execute CALL TARGETID command ; Syntax: _TARGETID (variable) _TARGETID: synchk '(' call ptrget ; get a pointer to variable push de ; save a pointer to variable ld a,(valtyp) push af ; save the type of variable call GetTargetID ld (dac+2),a xor a ld (dac+3),a pop af ; restore type of variable ld (valtyp),a ; set it to VALTYP ex (sp),hl ; save text pointer ; restore pointer to variable call ret_number pop hl ; restore text pointer synchk ')' ret ; Execute CALL SETTARGETID command ; Syntax: _SETTARGETID (x) ; x can be: - integer, singel precision, double precision ; - numeric value ; - expression _SETTARGETID: call getbyt ; Evaluate expression to a byte cp 4 ccf jp c,fcerr call SetTargetID ; Set Target ID and a ; Clear CY ret ; Execute CALL INQUIRY command ; Syntax: call inquiry (x,A$,B$,C$) ; x can be - integer single of double precision ; - numeric value ; - expression _INQUIRY: ld a,(hl) cp '(' jp nz,snerr inc hl call getbyt and a ; x < 0 ? jp m,fcerr ; Yes, illegal function call cp 8 ; x > 7 ? jp nc,fcerr ; Yes, illegal function call ld ix,($SECBUF) ; Get addres of sectorbuffer ld (ix+70h),a ; Store ID ld a,(hl) cp ',' jp nz,snerr inc hl ; String to Manufacturer push ix call ptrget pop ix ld a,(valtyp) cp 3 ; String ? jp nz,tmerr ; No, 'Type mismatch' error ld (ix+71h),d ld (ix+72h),e ; Store pointer to var. ld a,(hl) cp ',' jp nz,snerr inc hl ; String to Product push ix call ptrget pop ix ld a,(valtyp) cp 3 jp nz,tmerr ld (ix+73h),d ld (ix+74h),e ld a,(hl) cp ',' jp nz,snerr inc hl ; String to Revision push ix call ptrget pop ix ld a,(valtyp) cp 3 jp nz,tmerr ld (ix+75h),d ld (ix+76h),e ld a,(hl) cp ')' jp nz,snerr push hl ; Save text pointer ld a,(ix+70h) ; Get ID call Get_Inq ; Get inquiry jp c,diverr ld hl,($SECBUF) ld bc,8 add hl,bc ld de,buf ld bc,8 ld a,c ldir push hl ld h,(ix+71h) ld l,(ix+72h) push ix call ret_string ; Manufacturer pop ix pop hl ld de,buf ld bc,16 ld a,c ldir push hl ld h,(ix+73h) ld l,(ix+74h) push ix call ret_string ; Product pop ix pop hl ld de,buf ld bc,4 ld a,c ldir ld h,(ix+75h) ld l,(ix+76h) call ret_string ; Revision pop hl ; Restore text pointer inc hl and a ret ; _TEST added for test purpose ; Syntax: call test (....) ;_TEST: ; ld a,(hl) ; cp '(' ; jp nz,snerr ; inc hl ; call getbyt ; and a ; x < 0 ? ; jp m,fcerr ; Yes, illegal function call ; cp 8 ; x > 7 ? ; jp nc,fcerr ; Yes, illegal function call ; ld ix,($SECBUF) ; Get addres of sectorbuffer ; ld (ix+00h),a ; Store ID ; ld a,(hl) ; cp ',' ; jp nz,snerr ; inc hl ; ; String to Manufacturer ; ld (ix+01h),h ; ld (ix+02h),l ; Save text pointer, points to first string ; push ix ; call ptrget ; pop ix ; ld a,(valtyp) ; cp 3 ; String ? ; jp nz,tmerr ; No, 'Type mismatch' error ; ld a,(hl) ; cp ',' ; jp nz,snerr ; inc hl ; String to Product ; push ix ; call ptrget ; pop ix ; ld a,(valtyp) ; cp 3 ; jp nz,tmerr ; ld a,(hl) ; cp ',' ; jp nz,snerr ; inc hl ; String to Revision ; push ix ; call ptrget ; pop ix ; ld a,(valtyp) ; cp 3 ; jp nz,tmerr ; ld a,(hl) ; cp ')' ; jp nz,snerr ; The syntax of the command is now completely checked ; inc hl ; ld (ix+09h),h ; Save text pointer after command ; ld (ix+0ah),l ; ld a,(ix+00h) ; Get ID ; call Get_Inq ; Get inquiry ; jp c,diverr ; ld h,(ix+01h) ; ld l,(ix+02h) ; Get text pointer, points to first string ; push ix ; call ptrget ; pop ix ; inc hl ; Skip ',' ; ld (ix+01h),h ; ld (ix+02h),l ; Save text pointer, points to second string ; push de ; Save pointer to var. ; ld hl,($SECBUF) ; ld bc,0bh ; add hl,bc ; ld de,buf ; ld bc,8 ; ld a,c ; ldir ; Move Manufacturer to buf ; pop de ; push hl ; ex de,hl ; push ix ; call ret_string ; Manufacturer ; pop ix ; ld h,(ix+01h) ; ld l,(ix+02h) ; Get text pointer, points to second string ; push ix ; call ptrget ; pop ix ; inc hl ; Skip ',' ; ld (ix+01h),h ; ld (ix+02h),l ; Save text pointer, points to second string ; pop hl ; push de ; Save pointer to var ; ld de,buf ; ld bc,16 ; ld a,c ; ldir ; pop de ; push hl ; ex de,hl ; push ix ; call ret_string ; Product ; pop ix ; ld h,(ix+01h) ; ld l,(ix+02h) ; Get text pointer, points to third string ; push ix ; call ptrget ; pop ix ; pop hl ; push de ; Save pointer to var ; ld de,buf ; ld bc,8 ; ld a,c ; ldir ; pop hl ; call ret_string ; Revision ; ld h,(ix+09h) ; ld l,(ix+0ah) ; and a ; ret ; ************** END CALL STATEMENTS *************** ; AllocMem - Allocate Memory ; Input : HL = required memory size ; Output: HL = address of allocated memory ; if Carry is set there was not enough room, no mem allocated ; AllocMem: LD A,L OR H RET Z ; No memory to allocate ; XOR A SUB L LD L,A LD A,0 SBC A,H LD H,A LD C,L LD B,H ADD HL,SP CCF RET C ; LD DE,(BOTTOM) ; Get start of RAM SBC HL,DE RET C ; LD A,H CP 3 RET C ; PUSH BC LD HL,0 ADD HL,SP LD E,L LD D,H ADD HL,BC PUSH HL LD HL,(STKTOP) AND A SBC HL,DE LD C,L LD B,H INC BC POP HL LD SP,HL EX DE,HL LDIR POP BC LD HL,(HIMEM) ADD HL,BC LD (HIMEM),HL LD DE,0FDEAh ADD HL,DE LD (FILTAB),HL EX DE,HL LD HL,(MEMSIZ) ADD HL,BC LD (MEMSIZ),HL LD HL,(NULBUF) ADD HL,BC LD (NULBUF),HL LD HL,(STKTOP) ADD HL,BC LD (STKTOP),HL DEC HL DEC HL LD (SAVSTK),HL LD L,E LD H,D INC HL INC HL INC HL INC HL LD A,2 J$436B: EX DE,HL LD (HL),E INC HL LD (HL),D INC HL EX DE,HL LD BC,7 LD (HL),B ADD HL,BC LD (HL),B LD BC,0102h ADD HL,BC DEC A JR NZ,J$436B ; RET ; Init routine - is executed at system startup INIT: CALL DoTests ; Check MSX type and keys ; LD A,(DEVICE) OR A RET M ; DOS 2.x not initialised JP NZ,DskROM ; Install drives (DISKROM already ; installed) ; There is no DiskROM installed (yet), setup work area LD A,(BASVER) CP 1 RET C ; LD HL,HOKVLD BIT 0,(HL) ; Extended BIOS already installed? JR NZ,EXBIO_INS ; Yes ; SET 0,(HL) LD HL,EXTBIO LD B,0FH Clear3: LD (HL),0C9H INC HL DJNZ Clear3 ; EXBIO_INS: LD HL,(BOTTOM) LD DE,0C001h RST DCOMPR ; BOTTOM > 0c001h? ; RET NC ; Yes ; LD A,6 CALL SNSMAT ; RRCA ; SHIFT pressed? RET NC ; Yes, do not install HDD ; ; *M*v1.04 ; LD HL,0F3B0h ; LD DE,0F1C9h ; OR A ; Clear carry flag ; SBC HL,DE ; HL = 487 ; CALL NC,AllocMem call CalcWA_2 ; Calculate size of Work Area call AllocMem ; Allocate memory ; *M* ; RET C ; Not enough room ; PUSH HL ; Save address of allocated memory LD HL,0FE49h ; 439 bytes (65536 - 0fe49h) LD BC,0F1C9h Clear: XOR A LD (BC),A INC BC INC HL LD A,L OR H JR NZ,Clear ; LD HL,512 LD (AUTLIN),HL LD B,20 LD HL,0FB21h Clear1: LD (HL),A ; Fill with 0 INC HL DJNZ Clear1 ; LD HL,0F24Fh LD B,69h ; 105 Clear2: LD (HL),0C9h ; RET code INC HL DJNZ Clear2 ; ; Install code for RDPRIM routine (IN A,(0a8h) + RET) LD A,0DBH ; IN A,xx LD HL,0C9A8h LD (RDPRIM),A ; code for IN A,(xx) LD (RDPRIM+1),HL ; xx = a8h + RET code LD A,6 ; Keyboard ROW 6 CALL SNSMAT ; AND 00000010b ; Extract CTRL key LD (CTRL),A LD A,7 ; BEEP RST OUTDO ; LD C,0 LD DE,0FB21h EXX POP DE ; Work Area address JR J$443E ; Install drive(s) DskROM: LD HL,0FB21h LD B,4 ; Count all installed software drives XOR A DrvCnt: ADD A,(HL) ; Get # of drives RET C ; INC HL INC HL DJNZ DrvCnt ; CP 8 ; Allready 8 drives installed? RET NC ; Yes... ; LD HL,(AUTLIN) LD DE,512 RST DCOMPR ; JR NC,J$4424 ; LD (AUTLIN),DE J$4424: LD DE,0FB21h LD BC,0400h NxtEntr: LD A,(DE) ; Get # of software drives AND A ; Entry not used? JR Z,FreEntry ; No ; ADD A,C LD C,A INC DE INC DE DJNZ NxtEntr ; RET ; All entries used, can not install ; drives ; FreEntry: ; C contains # of already installed drives EXX call CalcWA_1 ; Calculate size of Work Area CALL AllocMem ; Allocate memory for Work Area ; RET C ; Not enough memory ; EX DE,HL ; DE = address of alloc. mem. J$443E: CALL GetSLTWRK ; Get SLTWRK address ; LD (HL),E ; Set Work Area address INC HL LD (HL),D EXX LD A,(CTRL) AND A ; CTRL key pressed? LD A,C ; Get # of installed drives CALL InsWork ; ADD A,L ; L contains # of partitions CP 9 LD A,L JR C,AllUsed ; LD A,8 ; Max # of drives SUB C ; Substract # of installed drvs AllUsed: PUSH BC LD (DE),A ; Store # of drives INC DE CALL WHEREAMI ; LD (DE),A ; Store slot ID POP BC ; C = number of drives to install LD B,0 LD HL,0F355h ADD HL,BC ADD HL,BC ; HL = 0F355h + 2 * drives PUSH HL DEC DE LD A,(DE) ; Get # of drives PUSH AF push de LD L,A LD H,0 LD D,H LD E,L ; DE = number of drives to inst. ADD HL,HL ADD HL,HL ADD HL,DE ADD HL,HL ADD HL,HL ADD HL,DE CALL AllocMem ; POP DE ; DE points to # of log. drives JR C,J$44C1 ; PUSH HL ; Address of alloc. mem. CALL ClrEndLn ; POP DE ; Alloc. mem. addr. POP BC ; B = # of drives to install POP HL ; HL = 0F355h + 2 * drives LD C,0 J$4484: LD (HL),E INC HL LD (HL),D INC HL PUSH BC PUSH DE PUSH HL LD HL,0FE00h ADD HL,SP LD SP,HL LD ($SECBUF),HL ; Set address of sector buffer LD A,C LD BC,(DPB) LD B,0 EX DE,HL CALL GETDPB ; LD HL,512 EX AF,AF' ADD HL,SP EX AF,AF' LD SP,HL POP HL POP DE LD BC,15h JR C,J$44B1 ; EX DE,HL ADD HL,BC EX DE,HL JR J$44B8 ; ; ----------------- J$44B1: PUSH HL LD HL,I$4508 ; Table-1 LDIR POP HL J$44B8: POP BC INC C DJNZ J$4484 ; LD HL,DEVICE INC (HL) RET ; ; ----------------- J$44C1: POP AF POP AF ; Dump XOR A LD (DE),A INC DE LD (DE),A RET ; Not supported calls NotSupp: RET ; Just return to caller DI HALT ; PRINT - Print a character PRINT: pop hl ; Points to text ld a,(hl) inc hl push hl or a ret z rst OUTDO jr PRINT ; OldCPUmode - Restore old CPU mode OldCPUmode: PUSH AF PUSH IX PUSH IY LD A,(CMASK) ; Get old CPU mode JR RestCPUmd ; Restore CPU mode ; ChgCPU ChgCPU: PUSH AF PUSH IX PUSH IY LD IX,0183h ; Get CPU mode LD IY,(EXPTBL-1) CALL CALSLT ; LD (CMASK),A ; Store CPU mode call Get_ID CPL RLCA RLCA AND 01H RestCPUmd: LD IX,0180h ; Change CPU mode LD IY,(EXPTBL-1) CALL CALSLT ; POP IY POP IX POP AF I$4508: RET ; DBP - Disk Paramter Block ; DPB: defb 0f0h ; Media ID defw 0200h ; Sector size defb 0fh ; Directory mask defb 04h ; Directory shift defb 01fh ; Cluster mask defb 06h ; Cluster shift defw 1h ; Top sector of FAT defb 02h ; Number of FATs defb 0feh ; Number of directory entries defw 29h ; Top sector of data area defw 0514h ; Amount of clusters + 1 defb 0ch ; Number of sector required for one FAT defw 19h ; Top sector of directory area ; DoTests - Check for Turbo-R, test GRAPH key etc. ; Also check for HDD (Target ID = 0-3) and set Host ID DoTests: EI LD A,(BASVER) CP 1 ; MSX2 or up? JR NC,TurboR ; pop af ; Not a MSX2 ret TurboR: LD A,6 ; Keyboard row 6 CALL SNSMAT ; BIT 2,A ; Test GRAPH JR NZ,IniScr ; pop af ; GRAPH is pressed ret IniScr: ld a,80 ld (LINL40),a xor a call CHGMOD ; Init text mode width 80 ; call ERAFNK ; Erase function keys ; Print InitTXT, Init WD33C93A, do selftest etc. ; Initialise: ; *N* ld a,(BASVER) cp 3 push af call nc,ChgCPU ; *N* call PrInitTxt ROMchk: ; *M*v1.08 ld a,1 ; *N* out (HARDWR),a ; Hardware reset WD3393A in a,(AUXSTAT) cp 30h ; BUSY + COMMAND IN PROGRESS ? jr nz,NoCHIP ; No, probably no WD3393A ld b,0 ; B=256 WaitIntP: in a,(AUXSTAT) dec b and 10000000b ; INTERRUPT PENDING? jr nz,WaitIntP ld a,17h out (REGSET),a in a,(RDWREG) ; Clear pending interrupt ; ld a,18h ; out (REGSET),a ; xor a ; out (RDWREG),a ; Execute RESET command NoCHIP: ; *M* LD HL,04000h LD (HL),A ChkROM: ADD A,(HL) INC HL BIT 7,H ; Address = 8000H ? JR Z,ChkROM ; No ; ; *N* pop af call nc,OldCPUmode ; *N* xor a OR A ; Error? JP NZ,ChkSumErr ; *M*v0.32 ; ; *N*v.032 ld bc,0640ch in a,(AUXSTAT) and c cp 0ch ; No SCSI controller? jr z,BusOk ; *N* ld c,20h Rtry: in a,(AUXSTAT) ; Read Auxiliary Status and c ; Busy? jr z,BusOk ; No ; call WAITL1 ; Wait ; djnz Rtry ; jp BusDown ; Failed, SCSI bus probably down BusOk: ; Test SCSI controller - WD3393A ld d,2 ld bc,baseport ChkLoop: out (c),d ld a,b out (RDWREG),a out (c),d in a,(RDWREG) cp b jp nz,SBICerr ; SBIC error ; djnz ChkLoop ; inc d ld a,d cp 0fh jr nz,ChkLoop call ChkSETDIAG ; Check DEL key for SETUP/DIAG call PRINT ; defb 'please wait --',0 ; Wait for HDD (ID = 0 - 3) ld b,30 WAITHDD: call TALE ; Print 'jumping' '-' ; *M* call GetTargetID ; Get Target ID ; *M* push bc call TstUnitRdy ; pop bc inc d dec d ; Status GOOD ? jp z,NOVAXIS ; Yes ; cp 42h ; call nz,WAIT ; djnz WAITHDD ; Try again ; Harddisk offline call PRINT defb CR,'Hard disk offline',CR,LF,0 pop af ; Dump return address ret ; ChkSumErr - ROM checksum error ChkSumErr: call PRINT ; defb 'ROM checksum error',CR,LF,0 jr HostFail ; BusDown - SCSI bus is down BusDown: call PRINT ; defb 'SCSI bus is down',CR,LF,0 ; jr HostFail ; SBICerr: call PRINT defb 'Controller test failed',CR,LF,0 HostFail: call PRINT ; defb 7 ; BELL defb 'Host interface self test failed',CR,LF,0 ; ld b,5 Wait3: call WAIT djnz Wait3 pop af ; Dump return address ret ; WAITL1: LD HL,01266h JR WAITL ; WAIT - wait WAIT: LD HL,0B7FBh WAITL: LD A,H OR L RET Z EX (SP),HL EX (SP),HL DEC HL JR WAITL ; InsWork - Install Workspace InsWork: PUSH AF PUSH BC PUSH DE ; ** SECURITY DUMMY ld hl,SECURE ; ** CALL GETWRK ; Get Drive Work Area in [HL] and [IX] ; LD (HL),0 LD D,H ; DE = Work Area address LD E,L INC DE ; DE = HL + 1 call CalcWA_3 ; Calculate size of Work Area LDIR ; Fill with 00h ; *N* ld a,(BASVER) cp 3 ld a,1 jr z,MSX_TBR dec a MSX_TBR: ; *N*v0.31 push af ld a,2 call CLKMOD ld b,11 call REDRAM and 00001100b ; Only bits 2 and 3 are needed srl a ld d,a pop af or d ; Now bit 0 contains MSX type ; bit 1 contains Multiple HDD support toggle ; bit 2 contains Driver Support toggle ; *M*v1.13.10 call ChkAut ld e,a ld a,2 call CLKMOD ld b,11 call REDRAM set 3,a bit 2,e jr nz,SecChk res 3,a SecChk: ld d,a ld b,11 call WRTRAM ld a,e ; *M* ; *M* ld d,a ld a,2 call CLKMOD ld b,12 call REDRAM and 00000100b ; Only bit 2 needed, contains ExtPrt sla a or d ld (ix+07h),a ; *N*v0.10 ld hl,CRLF call Print2 ld hl,220bh ld (XYpos),hl ld h,1 call POSIT ; *N*v0.10 LD HL,0FE00h ADD HL,SP LD SP,HL ; *** ; Test for HDD, start with Target ID read from clockchip ; Each ID is tested 8 times call CalcTab ld a,(iy+00h) ; Get Target ID ld c,0 TestID: push af ; Save Target ID push iy ; Save pointer call RdHDDpart ; Read partition table pop iy ; Restore pointer ; *M*v1.11.16 ; ld a,c ; Get # of installed log. drives ; cp maxdrv ; Exceeded max. drives? ; jr nc,J$468F ; Yes ; *M* pop af ; Restore Target ID inc d dec d ; Status GOOD? jr nz,HDDresp ; Yes add a,32 ; Try again jr nc,TestID HDDresp: inc iy ld a,(iy+00h) ; Get next ID bit 7,a ; End of table? jr z,TestID ; No ; *M* LD A,C OR A JR NZ,J$4690 ; INC C LD A,0F1H J$468F EQU $-1 J$4690: LD L,C LD IX,512 ADD IX,SP LD SP,IX POP DE POP BC POP AF ; v1.50 - 05/06/95 ei halt halt halt halt RET ; *N*v0.31 ; CalcTab - calculate ID table ; Input : - ; Output: IY = address of ID table, terminated with 128 CalcTab: ld a,2 call CLKMOD ld b,11 call REDRAM bit 2,a ; Multiple HDD support on? jr nz,MakMulTab ; Yes ; Calculate IDtable for single Target environment call GetTargetID ld iy,IDsTable and a ; Target ID 0 ? ret z ; Yes ld de,2 MaksTab: add iy,de dec a jr nz,MaksTab ret ; Calculate IDtable for Multiple HDD environment MakMulTab: ; *N*v0.31 call Get_ID and 7 ld iy,IDtable-32 ld de,32 inc a ld b,a MakTab: add iy,de djnz MakTab call GetTargetID and a ; Target ID 0? ; *M*v0.31 ; jr z,RghtT ; Yes ret z ; *M* ld b,a ld de,8 MakTab2: add iy,de djnz MakTab2 ; RghtT: ret ; RdHDDpart - Read HDD partition table ; Input : A = ID ; Output: C contains total # of log. drives ; IX = Address of free Work Area entry ; Modify: RdHDDpart: LD HL,4 ADD HL,SP LD ($SECBUF),HL ; Change sectorbuffer address PUSH BC ; C = number of installed log. drives PUSH IX ; Work Area address PUSH AF ; Save Target ID LD E,A call Get_ID INC A ADD A,E AND 7 jp z,NoResp ; LD A,2 OUT (REGSET),A LD A,12 ; Set Timeout to 96ms OUT (RDWREG),A LD A,E ; ID CALL TstUnitRdy LD E,A LD A,2 OUT (REGSET),A LD A,7Dh OUT (RDWREG),A ; Set Timeout Period to 1 second LD A,D OR A ; Status GOOD? jp z,TrnsPart ; Yes ; LD A,E CP 42H ; Error? jp z,NoResp ; POP AF PUSH AF CALL TstUnitRdy ; LD A,D OR A ; Status GOOD? jp z,TrnsPart ; Yes ; *N*v1.08 - added for CD-ROM cp 2 ; CHECK CONDITION? jr nz,NoResp ld b,0 ; Test max. 256 times pop af ; Get Target ID push af push bc call TstUnitRdy ld a,d or a ; STATUS GOOD? jr z,UnitRdy cp 2 ; CHECK CONDITION? jr nz,UnitNrdy ChkCnd: pop bc RetryCDR: pop af ; Target ID push af push bc push af call TstUnitRdy pop af inc d dec d ; STATUS GOOD? jr z,UnitRdy dec d dec d ; CHECK CONDITION? jr nz,UnitNRdy call GetSense push af call WAIT pop af dec d dec d ; CHECK CONDITION? jp z,UnitNrdy ; Yes and a ; NO SENSE? jr z,UnitNrdy ; Yes cp 2 ; NOT READY? jr z,ChkNrdy ; Yes cp 6 ; UNIT ATTENTION? jr nz,UnitNrdy ; No ChkNrdy: ld a,b ; Get Sense Code cp 29h ; POWER ON? jr z,UnitRdy ; Yes cp 3ah ; MEDIUM NOT PRESENT? jr z,UnitRdy ; Yes cp 04h ; LOGICAL UNIT NOT READY? jr nz,UnitNrdy ld a,c ; Get Additional Sense Code and a jr z,UnitNrdy dec a ; Becoming ready? jr nz,UnitNrdy ; No pop bc djnz RetryCDR ; Try again UnitNrdy: pop bc NoResp: POP AF ; No response from device POP IX POP BC LD D,2 ; Check Condition ; *N*v1.09.02 ; xor a ; inc a ; *N* RET UnitRdy: pop bc TrnsPart: POP AF PUSH AF ; ID ; Now get INQUIRY data of Device of current ID ; *N*v0.10 call GetInq pop af ; Target ID pop ix pop bc ; C = number of installed log. drv. inc d dec d ; Status GOOD ? ret nz ; No ld (TrgID),a ; Save Target ID ld a,c ld (LogDrv),a ; Save # of installed log. drives ; *N*v1.11.12 ld (DiffDrv),a ; *N* ld (WrkSav),ix ; Save Work Area address ; *N*v1.11.16 cp maxdrv jp nc,NrLogEx ; *N* call Rd_Cnv_Prt ; Read and convert partition table(s) jp c,ErrPartT ld a,(TabType) ; Get table type cp 1 ; PC ? jp z,InsPCTab cp 2 ; MSX ? jp z,InsMSXTab and a ; NOVAXIS ? jp z,InsNOVTab ; There's no partition table found ld a,'N' ; Indicate no partition found jp NoPartT ; ** SECURITY DUMMY ** ChkAut: push af push bc push ix ld hl,JurgenKramer ld de,0b200h ld bc,13 ldir ld hl,RevTxtJK push de ld bc,13 ldir pop de ld bc,0c7bh SecDecode: ld a,(de) xor c dec c ld (de),a inc de djnz SecDecode ld hl,0b200h push hl pop iy ld ix,0b200h+26 ld b,11 ChkAutStr: ld a,(ix-13) ld c,(iy+14) xor c cp (hl) jr nz,SecError inc hl inc ix inc iy djnz ChkAutStr ld hl,(C1_ADD) ld de,0b00h add hl,de ld d,l ld e,h ld b,11 ld hl,0b200h+13 ChkC1: ld a,(de) cp (hl) jr nz,SecError inc de inc hl djnz ChkC1 ld hl,(C2_ADD) ld de,0b00h add hl,de ld d,l ld e,h ld b,11 ld hl,0b200h+13 ChkC2: ld a,(de) cp (hl) jr nz,SecError inc de inc hl djnz ChkC2 pop ix pop bc pop af and 11111011b ret SecError: pop ix pop bc pop af or 4 ret ; ***** MSX PARTITIONS ***** ; InsMSXTab - Install MSX partition table InsMSXTab: ld ix,(WrkSav) ; Get Work Area address ld iy,TmpPDat ; Get address of temp. part. data ld a,(NrParts) ; Get # of partitions ld b,a ld a,(LogDrv) ; Get # of installed drives ld c,a ld de,8 ; Entry size ; Fill Network Write ID push bc ; Save # of partitions and installed drives push ix ; Save WA address push iy ; Save address of temp. part. data ld ix,PSecBuf+19eh ; Points to first partition entry FillMSXN: ld a,(ix+00h) ; Get Network Write ID rrca xor 11000000b ld (iy+07h),a ; Store in TmpPDat add ix,de add ix,de ; Next entry in PSecBuf add iy,de ; Next entry in TmpPDat djnz FillMSXN call CalcExtDrv pop iy pop ix pop bc NxtMSXP: dec (iy+00h) ; 12-bit FAT? jr nz,NoMSXPFAT ; No ld a,(TrgID) ; Get Target ID ld (ix+00h),a ; Store it WA ld a,(iy+07h) ; Get Write ID ld (ix+06h),a ; Store in WA call RdToggles bit 1,a ; Extended Partitions enabled? jr z,SkipMSXExt ld a,(iy+07h) ; and 00001111b call CalcExWrtID ld a,h ld (de),a ; Store Write ID in Ext. WA SkipMSXExt: ld a,(iy+01h) ; Get startsector LSB ld (ix+01h),a ; Store in WA ld a,(iy+02h) ld (ix+02h),a ld a,(iy+03h) ; Get startsector MSB ld (ix+03h),a ; Store in WA ld a,(iy+04h) ; Get # of sectors LSB ld (ix+04h),a ; Store in WA ld a,(iy+05h) ; Get # of sectors MSB ld (ix+05h),a ; Store in WA inc c ; Increase # of installed log. drives NoMSXPFAT: push de ld de,8 add ix,de add iy,de pop de inc de ld a,c cp maxdrv ; Exceeded max. # of log. drives? jp nc,NrLogEx djnz NxtPCP ; No, next MSX Partition jp NrLogEx ; ***** END MSX PARTITIONS ***** ; ****** PC PARTITIONS ****** ; InsPCTab - Install PC partition table InsPCTab: ld ix,(WrkSav) ; Get Work Area address ld iy,TmpPDat ; Get address of temp. part. data ld a,(NrParts) ; Get # of partitions ld b,a ld a,(LogDrv) ; Get # of installed drives ld c,a ld de,8 ; Entry size ; Set Network Write ID to Host ID call Get_ID ; Get Host ID add a,10h ; !!!!! push bc push iy push af call CalcExWrtID pop af FillPCN: ld (iy+07h),a ; Store network write ID add iy,de ; Next entry djnz FillPCN call CalcExtDrv pop iy pop bc ; NxtPCP: dec (iy+00h) ; 12-bit FAT? jr nz,NoMSXFAT ; No ld a,(TrgID) ; Get Target ID ld (ix+00h),a ; Store it WA ld a,(iy+07h) ; Get Write ID ld (ix+06h),a ; Store in WA call RdToggles bit 1,a ; Ext. Partitions enbled? jr z,NoExtPC ld a,h ; Get Network Write ID ld (de),a ; Store in Ext. WA NoExtPC: ld a,(iy+01h) ; Get startsector LSB ld (ix+01h),a ; Store in WA ld a,(iy+02h) ld (ix+02h),a ld a,(iy+03h) ; Get startsector MSB ld (ix+03h),a ; Store in WA ld a,(iy+04h) ; Get # of sectors LSB ld (ix+04h),a ; Store in WA ld a,(iy+05h) ; Get # of sectors MSB ld (ix+05h),a ; Store in WA inc c ; Increase # of installed log. drives NoMSXFAT: push de ld de,8 add ix,de add iy,de pop de inc de ld a,c cp maxdrv ; Exceeded max. # of log. drives? jr nc,NrLogEx djnz NxtPCP ; No, next PC Partition NrLogEx: ld (LogDrv),a ; Store # of log. drives ld (WrkSav),ix ; Store WA address push af ld a,(DiffDrv) ; Get # of driver installed before ld b,a pop af sub b ; Calc # of drives installed this run add a,30h jp NoPartT ; *N* ; ****** END PC PARTITIONS ****** ; ******* NOVAXIS PARTITIONS ******* ; InsNOVTab - Install NOVAXIS (Extended) partition table InsNOVTab: ; *N*v1.11.17 call RdToggles bit 1,a ; Extended Partitions enabled? ld a,'0' jp z,NoPartT ; No ; *N* ; *N*v1.11.06 ; ** SECURITY DUMMY ld hl,SECURE ; ** call GETWRK ld de,NRM_SIZE add ix,de set 7,(ix+01h) ; Indicate that the Ext. part. are in use ld de,NRM_SIZE+10h add hl,de ld a,(LogDrv) ; Get # of installed drives ld d,0 ld e,a add hl,de ex de,hl ; DE points to Write ID in Ext. WA ; ld ix,(WrkSav) ; Get Work Area address ld iy,TmpPDat ; Get address of temp. part. data call GetHost_ID ; Get Host ID ld h,1 ; Start with ID 0 and a ; Host ID 0? jr z,RdIDOk ld b,a MkRdID: sla h djnz MkRdID RdIDOk: ld a,(NrParts) ; Get # of partitions ld b,a ld a,(LogDrv) ; Get # of installed drives ld c,a ; NxtNOV: dec (iy+00h) ; 12-bit FAT? jr nz,NoRdPerm ; No ld a,(iy+06h) ; Get Read ID and h ; Permission to read this partition? jr z,NoRdPerm ; No, skip this partition ld a,(TrgID) ; Get Target ID ld (ix+00h),a ; Store in WA ld a,(iy+07h) ; Get Write ID ld (de),a ; Store in Ext. WA ld a,(iy+01h) ; Get startsector LSB ld (ix+01h),a ; Store in WA ld a,(iy+02h) ld (ix+02h),a ld a,(iy+03h) ; Get startsector MSB ld (ix+03h),a ; Store in WA ld a,(iy+04h) ; Get # of sectors LSB ld (ix+04h),a ; Store in WA ld a,(iy+05h) ; Get # of sectors MSB ld (ix+05h),a ; Store in WA inc c ; Increase # of log. drives NoRdPerm: push de ld de,8 add ix,de add iy,de pop de inc de ; Next Write ID in Ext. WA ld a,c cp maxdrv ; Exceeded max. # of log. drives? jp nc,NrLogEx djnz NxtNOV ; No, next PC Partition jp NrLogEx ; ErrPartT: ld a,'E' ; Indicate there was a error reading NoPartT: rst OUTDO ; Print message OkPartT: ld hl,CRLF call Print2 ld ix,(WrkSav) ld a,(LogDrv) ld c,a ret ; ******* END NOVAXIS PARTITIONS ******* ; CalcExtDrv - Calculate address of Extended Write ID table ; Input : - ; Output: DE points to Ext. Write ID table (only if Ext. Part. are enabled) ; Modify: AF,BC CalcExtDrv: call RdToggles bit 1,a ; Extended Partitions enabled? ret z ; No push hl push ix push iy call GETWRK ld de,NRM_SIZE add ix,de ld de,NRM_SIZE+10h add hl,de ld a,(LogDrv) ; Get # of installed drives ld d,0 ld e,a add hl,de ex de,hl ; DE points to Write ID in Ext. WA pop iy pop ix pop hl ret ; ** SECURITY DUMMY ** RevTxtJK: defb 'J' xor 123 defb 'u' xor 122 defb 'r' xor 121 defb 'g' xor 120 defb 'e' xor 119 defb 'n' xor 118 defb ' ' xor 117 defb 'K' xor 116 defb 'r' xor 115 defb 'a' xor 114 defb 'm' xor 113 defb 'e' xor 112 defb 'r' xor 111 ; CalcExWrtID - Calculate Extendend Write ID ; Input : A = old Network Write ID (c1h = ID 6 etc) ; Output: H = new network write ID ; Modify: AF CalcExWrtID: xor 255 and 7 push bc ld h,1 ; Start with ID 0 ld b,a and a ; ID 0? jr z,MSX_ID0 MakeMSXRd: sla h djnz MakeMSXRd MSX_ID0: pop bc ret ; PARTTAB.MAC - derived from READTAB.GEN ; Reads partition table ; Written by Roderik Muit ; Adapted by Jurgen Kramer for NOVAXIS SCSI BIOS ; (c) 1995 KMcs ; - 10/04/95 - ; Modified - 12/04/95 - .comment % Gebruikte labels: (NrParts)= aantal partities. (TabType) = type partitie, weet niet of je die nodig hebt dus heb hem maar laten zitten... 0 = Extended DOS/BERT/Novaxis 1.x(?) 1 = (oude) PC 2 = (oude) MSX (3 = gereserveerd voor MAK 3.0 in FDISK) 255 = No (valid) partition DrMAPDat = Drive-map-data. Formaat: 8 bytes voor A:-H: 0-(x-1) = partitienummer x staat naar deze drive toegemapt (x is nu 15?) 255 = Deze drive is niet meer aan een SCSI-partitie gekoppeld. Als de tabel niet gevonden wordt, wordt er 8 keer 255 in ingevuld. Ik heb geen flauw idee of dat handig is en heb het er dus voor de zekerheid maar in laten staan. PSecBuf = buffer voor inlezen partitiesector(s) TmpPDat = de uiteindelijke data: - Type (1 = MSX, enz.) - Beginsector (3 bytes LSB,MSB,MMSB) - Aantal sectoren (2 bytes LSB,MSB) - Read ID (bit 7 = ID 7, ..., Bit 0 = ID 0 - Write ID 1 = toegestaan, 0 = niet ) Partitie-indeling extended: (In principe HOEF je dit niet te weten omdat mijn leesroutine het allemaal afhandelt. Maar wie weet wanneer het van pas komt. Ook is het niet leuk als je ROM dingen kan inlezen waarvna je niet eens weet hoe ze in elkaar zitten, misschien...) Op partitie-entry 1 van de 4 (Dus op +1BEh) staat een normale partitie zoals je die kent. Op partitie-entry 2 staat een partitie met gegevens: - type nr. 5 - beginsector = sector waar volgende partitiedata staat (- aantal sectoren: heb ik op 1 gezet, weet niet zeker of dat moet.) Die volgende sector is weer precies zo opgebouwd met op +1BE een entry en op +1CE een type 5 en een verwijzing naar een volgende sector. Totdat er niet meer partities zijn, dan staat er gewoon niets op +1CE. (Verder staat aan het begin van elke partitiesector ook de 'EB FE 90' en de ID-naam daarachter ingevuld. Ik weet niet of het noodzakelijk is, bij de BERT is dit ook zo.) Verdere opmerking: De beginsector van elke partitie (en de 'beginsector' van de type 5 volgende partitietabel) zijn relatief ten opzichte van de partitiesector waarin die partitiedata staat. In de praktijk betekent dat dus dat voor de partitiedata overal beginsector 1 ingevuld staat, en voor de volgende partitiesector (partitielengte+1). (Dit is ook allemaal afgekeken van de BERT indeling.) - Nieuwe dingen toegevoegd aan deze standaard Extended MS-DOS partitie indeling: 1.) Door HPN (denk ik, ik neem aan dat dit geen standaard is): Vlak voor de 1e partitiedata, dus op bytes +1B6h - +1BDh, staan de lees/schrijftoegangen van deze partitie. - +1B6 is voor ID 0, ..., +1BD is voor ID 7 - bit 0 = schrijftoegang (1 = verboden) bit 1 = leestoegang (1 = verboden) Dus: 0 = lezen en schrijven 1 = niet schrijven (2 komt nooit voor volgens mij) 3 = deze partitie bestaat niet voor dit ID. 2.) Door mij (nog niet, maar in de toekomst misschien. Dit zal eraan liggen of jij het ooit in een ROM toepast): +1F6 - +1FD = de partitie-map-data voor drive A: t/m H: (0-254 = partitienummer dat bij opstarten naar deze drive toegemapt staat 255 = deze drive is niet meer aan deze HD toegewezen, alle volgende zijn ook 255. % ; Rd_Cnv_Prt - Read and Convert Parition table(s) ; Input : TrgID = ID, PSecBuf = address of 1k buffer, TmpPDat = temp. buffer ; DrMAPDat = address of drive MAP data ; Output: TabType = partition table type, 0 = Extended DOS, 1 = PC, 2 = MSX ; NrParts = # of partitions ; Error : Carry flag is set ; Modify: All Rd_Cnv_Prt: ld a,(TrgID) ; Get Target ID ld b,2 ld de,0 ld c,e ; Block 0 ld hl,PSecBuf call RdPartSecs ld a,d or a ; Status GOOD? jp nz,Error_0 ld hl,(PSecBuf+1fEH) ; Partitiontable found on block 0? ld de,0AA55h rst DCOMPR jr nz,readp2 ld a,(PSecBuf+1D2h) ; 2e part. = Extended DOS? Dan BERT formaat sub 5 jr z,readp6 ld hl,(PSecBuf+1A0h) ; Als 0,0,1,0 in '1e entry' dan MSX tabel ld de,0 rst DCOMPR jr nz,readp5 ld hl,(PSecBuf+1A2h) ld e,1 rst DCOMPR jr nz,readp5 ; MSX tabel ld a,2 ld ix,PSecBuf+19Eh jr readp4 ; Standaard (PC) tabel readp5: ld a,1 ld ix,PSecBuf+1BEh readp4: ld (TabType),a redp45: call inidmap jr fillp ; Geen partitietabel gevonden. readp2: ld a,255 ld (TabType),a ; call inidmap ; xor a inc a jp redpzx ; BERT tabel readp6: ; *N*v1.11.22 ld ix,PSecBuf+1beh ; *N* ld (TabType),a ; A=0 ld a,(PSecBuf+1F3h) ; Controleer op 'Drv' cp 68 jr nz,redp45 ld hl,(PSecBuf+1F4h) ld de,7672h rst DCOMPR jr nz,redp45 ld hl,PSecBuf+1F6h ; Klopt: neem drive-tabel over ld de,DrMAPDat ld bc,8 ldir ; *R*v1.11.22 ld ix,PSecBuf+1BEh ; *R*v1.11.22 ; vul gegevens in in TmpPDat ; IX = plaats in parttabel (al ingevuld) ; HL = plaats in TmpPDat ; B = partitienr. ; A'DE = sectornr. van partitietabel (<>0 bij BERT-partities) fillp: ld hl,TmpPDat ld de,0 xor a ld b,a fillpl: push bc push af push de ex af,af' ld a,(ix+4) ; type or a jp z,redpzz ld (hl),a inc hl ld c,(ix+8) ; beginsector ld b,(ix+9) ex af,af' ex de,hl add hl,bc ex de,hl adc a,(ix+10) ld (hl),e inc hl ld (hl),d inc hl ld (hl),a inc hl ex de,hl ; aantal sect. push ix pop hl ld bc,12 add hl,bc ldi ldi ld a,(TabType) cp 2 jr nc,fillp2 dec a jr z,fillp1 push ix ;BERT: codeer read/write ID pop hl push de ld b,8 fillpm: dec hl ld a,(hl) cp 4 jr nc,filp1b ; ID's niet goed ingevuld: zet op 255 cpl rrca ; write rl d rrca ; read rl e djnz fillpm pop hl ld (hl),e ; vul ID's in inc hl ld (hl),d jr filp1c fillp2: ex de,hl ; MSX tabel: read ID = 255, write ID = byte ld (hl),255 inc hl ld b,(ix) srl b inc b ld a,1 wid1a: rrca djnz wid1a ld (hl),a jr filp1c filp1b: pop de fillp1: ex de,hl ld (hl),255 ; oude DOS tabel: ID's 255 inc hl ld (hl),255 filp1c: inc hl redp01: ld a,(TabType) or a jr z,redp02 ; BERT ld bc,16 ; volgende partitie add ix,bc push hl push ix ; controle op laatste entry pop hl ld de,PSecBuf+1FEh rst DCOMPR pop hl jr c,redp03 redpbb: pop de pop af pop bc inc b redpzv: ld a,b redpzx: ld (NrParts),a and a ret redpzz: pop de pop af pop bc ld a,b ld (NrParts),a and a ret redp02: ld a,(PSecBuf+1D2h) cp 5 jr nz,redpbb ; Klaar pop de ; BERT: lees nieuwe partitiesector pop af ld c,(ix+24) ld b,(ix+25) ex de,hl add hl,bc ex de,hl adc a,(ix+26) ld c,a push af push de push hl ld b,1 ld hl,PSecBuf ld a,(TrgID) call RdPartSecs ld a,d or a jp nz,Error_1 ld ix,PSecBuf+1BEh pop hl redp03: pop de pop af pop bc inc b jp fillpl inidmap: ld hl,DrMAPDat ; Ini DrMAPDat ld b,8 redp22: ld (hl),255 inc hl djnz redp22 ret ; ** SECURITY ** C1_ADD: defb HIGH SecureC1 defb LOW SecureC1 ; ** Error_1: pop hl pop de pop af pop bc Error_0: scf ret ; RdPartSecs - Read Partition Sectors, with retries if necesarry ; Input : (TrgID) = Target ID ; B = # of blocks to read ; C D E = Start block ; HL = Data address ; Output: A = SCSI status ; D = Target Status ; E = Target Message ; Modify: BC,HL,IX,IY RdPartSecs: ld a,3 ; Max number of retries ld (MaxRet),a RetrPSR: push bc ; Save # of sectors & high block # push de ; Save block # low push hl ; Save data address ld a,(TrgID) ; Get Target ID call RdLogBlk ; Read blocks ld a,d ; Get Target Status and a ; Status GOOD? jr z,PartRdOk cp 2 ; CHECK CONDITION ? jr nz,PartRdOk ; No, just quit ld a,(TrgID) ; ID call GetSense inc d dec d ; GOOD? jr nz,PartRdOk ; No, quit and a ; NO SENSE? jr z,PartRdOk cp 6 ; UNIT ATTENTION? jr nz,PartRdOk ; No ld a,b ; Get Sense Code cp 29h ; POWER ON? jr z,RetryPSRd cp 30h ; MEDIUM error? jr nz,PartRdOk RetryPSRd: ld a,(MaxRet) dec a ld (MaxRet),a jr z,PartRdOk ; Retries exhausted pop hl pop de pop bc jr RetrPSR PartRdOk: ld hl,6 ; Dump saved paramters add hl,sp ld sp,hl ret ; ClrEndLn - Clear to End of Line ClrEndLn: CALL PRINT ; defb CR,ESC,'K',00h ret ; PartInfo - Calculate address of partition info of drive in Work Area ; 8 bytes / drive ; Input : A = drive # (0 - 5) ; Output: IX = Work Area address PartInfo: ADD A,A ; *2 ADD A,A ; *4 ADD A,A ; *8 LD E,A LD D,0 ; DE = A * 8 (A = drive no) CALL GETWRK ; Get work area in [IX] and [HL] ; ADD IX,DE ; IX = IX + (drvnr) * 8 RET ; GetUnitsOn - Get # of SCSI units online ; Input : - ; Output: A = # of units online, C = ID vector, D = HOST ID ; Modify: AF,BC,DE GetUnitsOn: ld a,2 out (REGSET),a ld a,12 out (RDWREG),a ; Set Timeout to 96ms call Get_Id cpl and 7 ld d,a ; D = HOST ID ld bc,0700h ; B = # of ID to test, C = # of units online ld a,c ld e,a ChkNxtId: cp d ; Host ID? jr z,UnNoRdy ; Yes, do not check this ID push bc push de call TstUnitRdy pop de pop bc cp 085h ; Ready? ; *M*0.49 jr nz,UnNoRdy ld a,c set 0,a ; Set LSB rrca ld c,a jr UnGoOn ; inc c UnNoRdy: ld a,c res 0,a ; Reset LSB rrca ld c,a ; *M* UnGoOn: inc e ; Next ID ld a,e djnz ChkNxtId ld a,2 out (REGSET),a ld a,7dh out (RDWREG),a ; Set Timeout to 1 second ld a,c ; Get # of units online rrca ld c,a ld b,8 ld e,0 CntUnits: rra jr nc,NotRDY inc e NotRDY: djnz CntUnits ld a,e ret ; DSKIO - Read / Write sectors ; ; Input : A = drive # (0 - 6) ; HL = transfer address ; DE = start sector ; B = # of sector to read ; C = media ID - F0h / F8h (for use with PC) ; Carry = 0 - read sectors otherwise write sectors (Carry = 1) ; Output: Carry = 0 - No error occurred ; Carry = 1 - error occurred -> A = error code, B = sectors remaining ; ; (error codes are taken from org. diskrom) ; 0 - Disk Write Protected ; 2 - Drive Not Ready ; 4 - CRC error ; 6 - Seek error ; 8 - Record Not Found ; 10 - Write error ; 12 - Bad parameter ; ; New DOS 2 errors: ; 18 - Not a DOS disk (DOS err) ; 20 - Incompatible disk (DOS err) ; ; 22 - Unformated disk (DOS err) ; ; Modify: all DSKIO: EI PUSH AF ; Save drive no. CP maxdrv ; Drive # exceeded max? JP NC,BADPRM ; Yes ; PUSH BC ; Save # of sectors & media ID PUSH DE ; Save start sector PUSH HL ; Save transfer address ; *M*v1.09.04 call DrvWork ; CALL PartInfo ; IX = work area address of curr. drv ; *N* ; POP HL POP DE POP BC POP AF ; C$4787: BIT 4,(IX+00h) ; 'Unformated disk'? JP NZ,NotFmt ; PUSH AF LD A,C ; Media ID ; *M*v1.02 cp 0f0h ; Normal MSX partition? jr z,MedIDok cp 0f8h ; PC partition? jp nz,BADPRM MedIDok: ; LD C,A ; C = 0 ld c,0 ; *M* PUSH DE ; Sector # LD A,B ; # of sectors to read DEC A ADD A,E LD E,A LD A,C ADC A,D LD D,A LD A,C ADC A,C LD C,A LD A,(IX+04h) ; Get max. sector # of current drive SUB E LD A,(IX+05h) SBC A,D LD A,0 SBC A,C POP DE ; Sector # JP C,J$485F ; LD A,E ; Calculate start sector # ADD A,(IX+01h) LD E,A LD A,D ADC A,(IX+02h) LD D,A LD A,0 ADC A,(IX+03h) LD C,A POP AF ; C D E = start sector # on HDD PUSH DE PUSH BC PUSH IX JR C,WRTSEC ; Carry = 1 > write sectors ; Test Purpose ; *N*E ; call Get_ID ; or 128 ; xor (ix+06h) ; and 10001111b ; jp nz,WrngID ; *N*E ; LD A,(IX+00h) ; Target ID CALL RdLogBlk ; JR J.4807 WRTSEC: ; *M*v1.09.04 call WrtPermit ; Permission to write? jp c,WrngID ; No ; call Get_ID ; *** ; OR 10000000b ; XOR (IX+06h) ; Network Write ID # ; AND 10001111b ; JP NZ,WrngID ; Wrong ID, not allowed to write ; *M* ; LD A,(IX+00h) ; Target ID PUSH AF ; Save ID PUSH BC ; Save # of blocks to read PUSH DE ; and save start block # PUSH HL ; Save data address ; *T*v1.05 ; bit 7,(ix+35h) ; Driver functions enabled? ; call nz,ChkDrvID ; Yes, check driver ID ; jp c,ToExtDrv ; Jump to driver ; *T* CALL WrLogBlk ; Write sector ; LD B,A LD A,(0F30Dh) ; Get VERIFY byte OR A ; VERIFY ON? JP Z,J.4801 ; No ; LD A,D OR A ; Status GOOD? JR NZ,J.4801 ; No ; call Get_ID ; *** BIT 4,A JR NZ,J.4801 ; POP HL POP DE POP BC POP AF CALL Verify ; Verify written blocks ; jr J.4807 J.4801: LD A,B LD HL,8 ADD HL,SP LD SP,HL ; Dump saved parameters J.4807: POP IX POP BC POP HL ; Sector # CP 42H LD A,2 ; 'Drive Not Ready' SCF RET Z ; LD A,D ; C$4812: OR A ; Status GOOD? RET Z ; Yes ; PUSH HL PUSH BC LD A,(IX+00h) ; Get Target ID PUSH IX CALL ReqSense ; POP HL ; Work Area address PUSH AF INC D DEC D ; Status GOOD? JR NZ,J$4843 ; No ; LD A,(IX+02h) ; Get (Extended) Sense Key CP 06h ; 'Unit Attention' ? JR NZ,J$4847 ; No ; PUSH HL ; ** SECURITY DUMMY ld hl,SECURE ; ** CALL GETWRK ; POP IX LD A,(IX+00h) ; Target ID OR 08H LD DE,8 LD B,6 J$483B: CP (HL) JR NZ,J$4840 ; RES 3,(HL) J$4840: ADD HL,DE DJNZ J$483B ; J$4843: POP AF POP BC POP DE RET ; ; ----------------- J$4847: POP AF POP BC POP DE BIT 7,(IX) ; Sense Data Valid ? RET Z ; No ; PUSH AF LD A,B SUB (IX+6) ADD A,E LD B,A POP AF RET ; Drive 'Write Protected' - Network Write ID # incorrect WrngID: POP AF POP BC POP AF LD A,0 ; 'Write protected error' SCF RET J$485F: LD A,(IX+04h) ; Get # of sectors in partition (MSB) SUB E LD C,A INC C LD A,(IX+05h) ; Get # of sectors in partition (LSB) SBC A,D JR C,J$487A ; LD A,B SUB C LD B,A POP AF PUSH BC LD B,C LD C,0F0H ; Media ID CALL C$4787 ; JR C,J$487F ; POP BC LD A,0F1H J$487A EQU $-1 ; 'POP AF' LD A,8 ; 'Sector not found' SCF RET ; ; ----------------- J$487F: POP DE PUSH AF LD A,B ADD A,D LD B,A POP AF RET ; Bad Parameter Error BADPRM: POP AF PRMBAD: LD A,12 ; 'Bad parameter' SCF ; Set carry to indicate error occurred RET ; Called from entry 4013h ; DSKCHG - Check if disk is changed ; Input : A = drive # (0-5) ; HL = base address of DPB ; Output: If Carry is set, reg A contains error code else ; register B contains diskstatus ; B = 1 , disk unchanged ; B = 0 , unknown ; B = 255, disk is changed ; Modify: AF,BC,DE,HL,IX DSKCHG: EI CP 6 ; Drive # > 5 JR NC,PRMBAD ; Yes ; OR A PUSH AF PUSH HL CALL PartInfo ; Get Work Area of current drive ; POP HL call Get_ID ; *** XOR (IX+06h) AND 7 JR NZ,J$48B2 ; POP AF LD B,1 BIT 3,(IX+00h) RET NZ ; SET 3,(IX+00h) CALL GETDPB ; LD B,255 RET ; ; ----------------- J$48B2: POP AF CALL GETDPB ; LD B,0 RET ; Called from entry 4016h (Get DPB address) ; GETDPB - Get Disk Parameter block ; Input : A = drive # ; HL = data address ; Output: if carry is set, the A contains error code ; Modify: AF,BC,DE,HL,IX,IY ; Disk Parameter Block: ; ; +00 - Drive # ; +01 - Media ID (0f0h) ; +02/03 - Bytes/sector (0200h) ; +04 - Directory mask ; +05 - Directory shift ; +06 - Cluster mask ; +07 - Cluster shift ; +08/09 - First FAT sector ; +0a - Number of FATs ; +0b - # of directory entries ; +0c/0d - First data sector ; +0e - # of clusters + 1 ; +10 - # of sectors/FAT ; +11/12 - First directory sector ; +13/14 - FAT address (not used) GETDPB: EI CP 6 ; Drive # > 5 ? JR NC,PRMBAD ; Yes ; PUSH AF PUSH HL CALL PartInfo ; Get drive work area of current drive ; in [IX] ; POP HL POP AF BIT 4,(IX+00h) JR Z,J$48CF ; NotFmt: LD A,22 ; 'Unformated disk' error SCF RET ; ; ----------------- J$48CF: PUSH HL LD HL,($SECBUF) ; Transfer to sectorbuffer PUSH HL LD A,(IX+00h) ; Target ID LD B,1 ; 1 sector read LD C,(IX+03h) LD D,(IX+02h) LD E,(IX+01h) ; Form first sector # of partition CALL RdLogBlk ; Read bootsector ; POP IY ; Sectorbuffer address POP IX ; Memory address LD A,D CALL C$4812 ; Request Sense ; RET C ; Error ; LD A,(IY+15h) ; Get Media descriptor LD (IX+01h),A CP 0F0h LD A,18 ; 'Not a DOS disk' error SCF RET NZ ; LD L,(IY+0eh) LD H,(IY+0fh) ; Get # of reserved sectors LD (IX+08h),L LD (IX+09h),H ; Store LD A,(IY+10h) ; Get # of FATs LD (IX+10),A LD E,(IY+16h) LD D,(IY+17h) ; Get # of sectors/FAT LD (IX+16),E LD B,A J$4916: ADD HL,DE DJNZ J$4916 ; LD (IX+17),L LD (IX+18),H LD E,(IY+11h) LD D,(IY+12h) ; Get # of directory entries LD (IX+11),E LD C,(IY+0bh) LD B,(IY+0ch) ; Get # of bytes/sector LD (IX+2),C LD (IX+3),B SRL B RR C SRL B RR C SRL B RR C SRL B RR C SRL B RR C DEC C LD (IX+4),C ADD A,E LD E,A RL D J$4950: INC B RR C JR C,J$4950 ; DEC B LD (IX+5),B J$4959: SRL D RR E DJNZ J$4959 ; ADD HL,DE LD (IX+12),L LD (IX+13),H EX DE,HL LD L,(IY+13h) LD H,(IY+14h) ; Get total # sectors OR A SBC HL,DE LD A,(IY+0dh) ; Get # of sectors/cluster DEC A LD (IX+6),A J$4977: INC B RRCA JR C,J$4977 ; LD (IX+7),B DEC B JR Z,J$4987 ; J$4981: SRL H RR L DJNZ J$4981 ; J$4987: INC HL LD (IX+14),L LD (IX+15),H OR A RET CHOICE: LD HL,FmtMsg RET ; FmtMsg: DEFM CR,LF defm '1 - Write protect partition',CR,LF DEFM '2 - Write enable partition',CR,LF,CR,LF,0 ; DSKFMT - 'Format' disk (write enable- or protect partition) ; Input : A = choice, D = drive # ; Output: Carry = 1 > error, A contains error code: A = 12 Bad Parameter ; Modify: AF,DE,HL,IX DSKFMT: LD E,A CP 3 ; Choice within range? JR NC,WrngChc ; No ; LD A,D CP 6 ; Drive # within range? WrngChc: LD A,12 ; Bad Parameter CCF RET C ; DEC E ; Choice was 0? SCF RET M ; Yes ; PUSH DE ; D = drive, E = choice (0 - 1) LD A,D CALL PartInfo ; Get Work Area of drive # ; POP DE LD D,0 LD HL,Table2 ADD HL,DE ADD HL,DE LD A,(HL) INC HL LD H,(HL) LD L,A JP (HL) ; Write Enable- or Protect Partition Table2: defw WpPart defw WePart ; Write enable partition WePart: call Get_ID xor (ix+06h) and 7 jr z,FmtIDok ; Host is allowed to WE partition DskWP: ld a,0 ; 'Disk Write Protected' scf ret FmtIDok: set 7,(ix+06h) ret ; SET 7,(IX+06h) ; call Get_ID ; **** ; XOR (IX+06h) ; AND 7 ; RET Z ; ; LD A,0 ; 'Disk Write Protected' ; SCF ; RET ; Write protect partition WpPart: RES 7,(IX+6) RET ; ?.4A08: SCF ; RET ; Logically format partition ; ;LogFmt: bit 7,(ix+06h) ; Disk write protected? ; jr z,DskWP ; Yes ; call Get_ID ; xor (ix+06h) ; and 7 ; Is host allowed to format? ; jr nz,DskWP ; No ; ld a,6 ; Just for test ; scf ; ret ; ** SECURITY ** C2_ADD: defb HIGH SecureC2 defb LOW SecureC2 ; ** ; Called from entry 401fh ; STPDRV - Stop all connected drives ; Input : - ; Output: - ; Modify: AF,BC,DE,HL,IX STPDRV: CALL GETWRK ; LD BC,6 OR C J$4A11: LD A,(HL) PUSH HL PUSH BC PUSH AF CALL NZ,StrtStpUn ; POP AF POP BC POP HL J$4A1B: DEC C RET Z ; LD DE,8 ADD HL,DE BIT 4,(HL) JR NZ,J$4A1B ; XOR (HL) AND 0E7H JR J$4A11 ; SetHOST_ID - Set host ID ; Input : A = ID (4-7) ; Output: Carry is set when error occurred ; Modify: AF,D SetHOST_ID: cp 4 ret c cp 8 ret nc ROM_SetHost: ld d,a push bc push de push hl xor a out (REGSET),a out (RDWREG),a ; Set Own ID to zero ; *M*v0.45 ld a,2 call CLKMOD ld b,12 call REDRAM and 00001100b ; Bit 2 and 3 must be saved res 2,a or d ; *M* ld a,2 call CLKMOD ld b,12 call WRTRAM ; Store new ID call SetWD3393 ; Reinitialise pop hl pop de pop bc ret ; SndDiag - 'Send Diagnostics' (perform Self Test) ; Input : A = LUN + ID ; Output: A = SCSI status ; E = msg, D = Target Status SndDiag: PUSH AF ; ID LD A,03H OUT (REGSET),A LD A,SENDIAG ; Send Diagnostic command OUT (RDWREG),A POP AF PUSH AF AND 11100000b PUSH AF OR 00000100b ; Set SelfTest bit JR J$4C34 ; TstUnitRdy - 'Test Unit Ready' ; Input : A = ID ; Output: A = SCSI status ; D = Target Status ; E = msg ; Modify: AF,bC, TstUnitRdy: PUSH AF ; ID LD A,03H OUT (REGSET),A XOR A OUT (RDWREG),A ; Test Unit Ready command POP AF PUSH AF AND 11100000b PUSH AF J$4C34: OUT (RDWREG),A ; Logical Unit Number LD C,RDWREG XOR A OUT (RDWREG),A ; Reserved OUT (RDWREG),A ; Reserved OUT (RDWREG),A ; Reserved JR J$4C5A ; StrtStpUn - 'Start / Stop Unit' ; Input : A = ID ; B = 0 - Stop Unit ; B = 1 - Start Unit ; Output: A = SCSI status, D = Target Status, E = msg StrtStpUn: PUSH AF ; ID LD A,03H OUT (REGSET),A LD A,STSTOP ; Start / Stop Unit command OUT (RDWREG),A POP AF PUSH AF AND 11100000b PUSH AF OUT (RDWREG),A ; Logical Unit Number LD C,RDWREG XOR A OUT (RDWREG),A ; Reserved OUT (RDWREG),A ; Reserved OUT (C),B ; Start / Stop J$4C5A: OUT (RDWREG),A ; 0 LD A,0FH OUT (REGSET),A POP AF RLCA RLCA RLCA OUT (RDWREG),A ; Target LUN LD A,12H OUT (REGSET),A XOR A OUT (RDWREG),A ; Transfer count (MSB) OUT (RDWREG),A ; Transfer count OUT (RDWREG),A ; Transfer count (LSB) POP AF AND 07H OUT (RDWREG),A ; Destination ID J.4C76: IN A,(AUXSTAT) OR A ; Interrupt pending? JP P,J$4C8A ; No ; LD A,17H OUT (REGSET),A EX (SP),HL EX (SP),HL IN A,(RDWREG) ; Read SCSI status OR A ; Reset state? CALL Z,SetWD3393 ; Yes ; JR J.4C76 J$4C8A: AND 00110000b ; Level 2 Command In Progress? JR NZ,J.4C76 ; Yes ; LD IX,RT_01 CIP_5: IN A,(AUXSTAT) AND 00010000b ; Command In Progress ? JR NZ,CIP_5 ; Yes ; LD A,10h OUT (REGSET),A XOR A OUT (RDWREG),A ; Set Command Phase LD A,18H OUT (REGSET),A LD A,SelATNTrn ; Select-with-!ATN and-Transfer OUT (RDWREG),A JP TermAct ; RdLogBlk - Read Sector Direct ; Input : A = ID ; B = # of sectors to read ; C D E = 21 bits sector # ; HL = transfer address ; ; Output: ; A = SCSI status ; D = Target Status ; E = msg ; HL = data address RdLogBlk: PUSH AF ; Save SCSI ID LD A,3 OUT (REGSET),A LD A,READ ; Direct Access read cmd OUT (RDWREG),A POP AF ; ID PUSH AF AND 11100000b PUSH AF OR C ; Form LUN + Log. Block Addr. (MSB) OUT (RDWREG),A LD C,RDWREG OUT (C),D ; Logical Block Address OUT (C),E ; Logical Block Address (LSB) XOR A OUT (C),B ; Transfer length (blocks) ; OUT (RDWREG),A out (c),a LD A,0FH OUT (REGSET),A ; Select target LUN register POP AF RLCA RLCA RLCA ; OUT (RDWREG),A ; Set target LUN out (c),a LD A,12H OUT (REGSET),A XOR A ; OUT (RDWREG),A ; Transfer count (MSB) out (c),a SLA B ; Calculate # of bytes to read OUT (C),B ; Transfer count OUT (RDWREG),A ; Transfer count (LSB) POP AF ; SCSI ID AND 07H out (c),a ; OUT (RDWREG),A ; Set Destination ID Level2_CIP: IN A,(AUXSTAT) ; Read Auxiliary status OR A ; Interrupt pending? JP P,NoIntP_1 ; No ; LD A,17H OUT (REGSET),A ; Interrupt pending EX (SP),HL EX (SP),HL IN A,(RDWREG) ; Read SCSI status OR A ; Reset state ? CALL Z,SetWD3393 ; Yes ; JR Level2_CIP ; NoIntP_1: AND 00110000b ; Level II command in progress? JR NZ,Level2_CIP ; Yes ; LD IX,RT_02 CIP_6: IN A,(AUXSTAT) AND 00010000b ; Command In Progress ? JR NZ,CIP_6 ; Yes ; LD A,10h OUT (REGSET),A XOR A OUT (RDWREG),A ; Set command phase to disconnect state LD A,18h OUT (REGSET),A LD A,SelATNTrn ; Select-with-!ATN and-Transfer OUT (RDWREG),A LD A,19h OUT (REGSET),A ; Select Data Register ; ** SECURITY call RdToggles rrca jr c,SecSlowRd ; ** CALL FastExec ; Change CPU mode and move transfer ; routine to sectorbuffer ; This part of code can be moved to the sectorbuffer for highspeed data ; transfer ; *** BEGMOV *** GetData: IN A,(AUXSTAT) ; (2) RRCA ; (1) Data Buffer Ready? JR NC,BufNrdy_1 ; (2) No ld b,64 ; (2) inir ; (2) JR GetData ; (2) nop ; (1) nop ; (1) BufNrdy_1: AND 01000000b ; (2) Interrupt pending? JR NZ,IntP_1 ; (2) Yes ; JR GetData ; (2) ; *** ENDMOV *** IntP_1: call TbrCPUres ; Restore CPU mode when Turbo-R JP TermAct ; Terminate actions ; *** SECURITY *** SecSlowRd: IN A,(AUXSTAT) ; (2) RRCA ; (1) Data Buffer Ready? JR NC,SecBufNrdy ; (2) No ini ; (2) JR SecSlowRd ; (2) nop ; (1) nop ; (1) nop ; (1) nop ; (1) SecBufNrdy: AND 01000000b ; (2) Interrupt pending? JR NZ,SecIntP ; (2) Yes ; JR SecSlowRd ; (2) SecIntP: call TbrCPUres ; Restore CPU mode when Turbo-R JP TermAct ; Terminate actions ; ModeSel - 'Mode Select' ; Input : A = LUN + ID ; B = Parameter List Length ; ; Output: A = SCSI Status ; D = Target status ; E = Message ModeSel: EI PUSH AF ; Save ID LD A,03H OUT (REGSET),A LD A,MODSEL ; Mode Select command OUT (RDWREG),A POP AF PUSH AF AND 11100000b ; Form Target LUN PUSH AF OUT (RDWREG),A LD C,RDWREG XOR A OUT (RDWREG),A ; Reserved OUT (RDWREG),A ; Reserved OUT (C),B ; Parameter List Length OUT (RDWREG),A ; 0 LD A,0FH OUT (REGSET),A POP AF RLCA RLCA RLCA OUT (RDWREG),A ; Target LUN LD A,12H OUT (REGSET),A XOR A OUT (RDWREG),A ; Transfer count (MSB) OUT (RDWREG),A ; Transfer count OUT (C),B ; Transfer count (LSB) JP J.50BC ; FmtUnit - 'Format Unit' ; Input : A = ID , B = FmtData, CmpLst, Defect List Format ; DE = interleave (MSB - LSB) ; HL = address for format data ; Output: FmtUnit: EI PUSH AF ; Save ID LD A,03H OUT (REGSET),A LD A,FORMAT OUT (RDWREG),A POP AF PUSH AF AND 11100000b PUSH AF OR B OUT (RDWREG),A ; Target LUN, FmtData, CmpLst, Defect ; List Format LD C,RDWREG XOR A OUT (RDWREG),A ; 0 OUT (C),D ; Interleave (MSB) OUT (C),E ; Interleave (LSB) OUT (RDWREG),A ; 0 LD A,0FH OUT (REGSET),A POP AF RLCA RLCA RLCA OUT (RDWREG),A ; Target LUN LD A,12H OUT (REGSET),A XOR A OUT (RDWREG),A ; Transfer count (MSB) LD D,A LD E,A BIT 4,B ; FmtData = 1 ? JR Z,J$4DA6 ; No ; PUSH HL INC HL INC HL LD D,(HL) INC HL LD E,(HL) POP HL INC DE INC DE INC DE INC DE J$4DA6: OUT (C),D ; Transfer count (defect list length?) OUT (C),E ; Transfer count (LSB) JP J.50BC ; Verify - 'Verify' ; Input : A = ID, B = Verification Length ; C D E = 21 bits Logical Block # ; Output: Verify: PUSH AF ; ID LD A,03H OUT (REGSET),A LD A,_VERIFY ; Verify command OUT (RDWREG),A POP AF PUSH AF AND 11100000b PUSH AF OUT (RDWREG),A ; Logical Unit Number XOR A OUT (RDWREG),A ; Logical Block Address (MSB) LD A,C OUT (RDWREG),A ; Logical Block Address LD C,RDWREG OUT (C),D ; Logical Block Address OUT (C),E ; Logical Block Address (LSB) XOR A OUT (RDWREG),A ; Reserved OUT (RDWREG),A ; Verification Length (MSB) OUT (C),B ; Verification Length (LSB) OUT (RDWREG),A ; 0 LD A,0FH OUT (REGSET),A POP AF RLCA RLCA RLCA OUT (RDWREG),A ; Target LUN LD A,12H OUT (REGSET),A XOR A OUT (RDWREG),A ; Transfer count (MSB) SLA B ; Calc # of bytes to compare OUT (C),B ; Transfer count OUT (RDWREG),A ; Transfer count (LSB) JP J.50BC ; WrLogBlk - Write Sector Direct ; Input : A = ID ; B = # of sectors to read ; C D E = 21 bits sector # ; HL = transfer address ; Output: A = ; D = Target Status ; E = msg WrLogBlk: PUSH AF ; Save ID LD A,03H OUT (REGSET),A LD A,WRITE ; Write command OUT (RDWREG),A POP AF ; ID PUSH AF AND 11100000b PUSH AF OR C OUT (RDWREG),A ; Target LUN + Log. Block Addr. (MSB) LD C,RDWREG OUT (C),D ; Logical Block Address OUT (C),E ; Logical Block Address (LSB) XOR A OUT (C),B ; Transfer Length OUT (RDWREG),A ; 0 LD A,0FH OUT (REGSET),A POP AF ; Target LUN (always 0) RLCA RLCA RLCA OUT (RDWREG),A ; Write Target LUN register LD A,12H OUT (REGSET),A XOR A OUT (RDWREG),A ; Transfer count (MSB) SLA B ; Calculate # of bytes to be transf. OUT (C),B ; Transfer count OUT (RDWREG),A ; Transfer count (LSB) POP AF ; ID AND 07h OUT (RDWREG),A ; Destination ID J.4E24: IN A,(AUXSTAT) ; Read Auxiliary status OR A ; Interrupt pending JP P,J$4E38 ; No ; LD A,17H OUT (REGSET),A EX (SP),HL EX (SP),HL IN A,(RDWREG) ; Read SCSI status OR A ; Reset State? CALL Z,SetWD3393 ; Yes ; JR J.4E24 J$4E38: AND 00110000b ; BuSY? , Command In Progress? JR NZ,J.4E24 ; LD IX,RT_03 J$4E40: IN A,(AUXSTAT) AND 00010000b ; Command In Progress? JR NZ,J$4E40 ; Yes ; LD A,10H OUT (REGSET),A XOR A OUT (RDWREG),A ; Command Phase = 0 LD A,18H OUT (REGSET),A LD A,SelATNTrn ; Select-with-!ATN and-Transfer OUT (RDWREG),A LD A,19H OUT (REGSET),A ; Select data register CALL FastExec ; ***** BEGMOV ***** WrLogBlk WrData: IN A,(AUXSTAT) RRCA ; Data Buffer Ready? JR NC,BufNrdy2 ; No ; LD B,4 ; Write 4 bytes a time OTIR nop nop JR WrData BufNrdy2: AND 01000000b ; Interrupt pending? JR NZ,IntP_2 JR WrData ; ***** ENDMOV **** WrLogBlk IntP_2: call TbrCPUres jp TermAct ; FastExec - Move Read/Write code to RAM and execute command ; (only when Transfer address and $SECBUF address do not overlap) FastExec: call TbrCPUset BIT 7,H ; Transfer address above 7FFFh ? JR Z,Pag1_Trn ; No LD DE,($SECBUF) ; Get address of sectorbuffer LD A,E ; Compare DE and HL SUB L JR NZ,MovCode ; Lower bytes don't match ; LD A,D SUB H AND 3FH RET Z ; DE = HL, so the transfer program ; can not be moved to RAM (secbuff) ; just execute transfer routine ; in (slow) ROM ; ***** following comments are for RdLogBlk only ***** MovCode: EX (SP),HL ; HL = (SP) = GetData ; (SP) = transfer address ($SECBUF) PUSH BC ; Save # of sectors (reg. B) LD BC,19 ; 19 bytes to be transfered LDIR ; Move to sectorbuffer LD A,0c9h LD (DE),A ; Put 'RET' at end of code POP BC EX (SP),HL ; HL = transf. addr, (SP) = ret. addr LD IY,($SECBUF) JP (IY) ; Execute routine (Read sectors) ; Transfer address < 8000h Pag1_Trn: EX (SP),HL ; HL = GetData, (SP) = transf. addr. PUSH BC ; Save # of sectors to read (reg. B) PUSH HL ; Save address of tranf. routine LD BC,6 LD DE,($SECBUF) LD HL,SltRtn ; Slot routine LDIR ; Move to sectorbuffer EX (SP),HL ; HL = 4D1AH, (SP) = 4ECEh+6h LD BC,19 LDIR ; Move transf. routine EX (SP),HL ; HL = 4ECEh+6h, (SP) = 4D1Ah + 19 LD BC,16 LDIR CALL WHEREAMI ; Get slot ID ; POP HL ; HL = 4D1AH POP BC ; B = # sectors to read EX (SP),HL ; HL = 4D1Ah + 19, (SP) = 4ECEh+6+16 LD IY,($SECBUF) ; Get sectorbuffer address LD (IY+26),A ; Store slot ID LD A,(RAMAD1) ; Get RAM slot ID for page 1 PUSH IX PUSH BC PUSH HL LD H,40H JP (IY) ; Enable RAM slot and read sectors ; Moved when transfer address < 8000h SltRtn: CALL ENASLT ; 3 ; POP HL ; 1 POP BC ; 1 EI ; 1, total = 6 ; Moved when transfer address < 8000h PUSH HL ; 1 CALL 0F368h ; 3 ; LD A,0 ; 2 (value 00h is replaced by ROM slot ID) LD H,40H ; 2 CALL ENASLT ; 3 ; POP HL ; 1 POP IX ; 2 EI ; 1 RET ; 1, tot. = 16 ; ***** End RdLogBlk comments ***** ; ReqSense - 'Request Sense' (12h bytes) (Extended Sense Data Format) ; Input : A = LUN + ID ; Output: Carry flag set when error occurred ; A = error code (DOS error code) ; ; ; IX = address of sectorbuffer filled with Sense info ReqSense: PUSH AF ; Save ID LD A,03H OUT (REGSET),A OUT (RDWREG),A ; Request Sense command POP AF PUSH AF AND 11100000b ; Logical Unit Number PUSH AF OUT (RDWREG),A LD C,RDWREG XOR A OUT (RDWREG),A ; Reserved OUT (RDWREG),A ; Reserved LD B,12H OUT (C),B ; Allocation length = 12h OUT (RDWREG),A ; 0 LD A,0FH OUT (REGSET),A POP AF ; Logical Unit Number RLCA RLCA RLCA OUT (RDWREG),A ; Target LUN LD A,12H OUT (REGSET),A XOR A OUT (RDWREG),A ; Transfer count (MSB) OUT (RDWREG),A ; Transfer count OUT (C),B ; Transfer count (LSB) POP AF AND 07H OUT (RDWREG),A ; Destination ID LD HL,($SECBUF) ; Get address of sectorbuffer PUSH HL CALL C.506B ; Execute command ; POP IX ; Address of sectorbuffer CP 42h LD A,2 ; 'Drive Not Ready' SCF RET Z ; BIT 3,D ; Status BUSY? LD A,24 ; SCF RET NZ ; INC D DEC D ; Status GOOD? LD A,12 ; Bad Parameter SCF RET NZ ; No ; ; Noextended Sense Data Format ; ; ======================================================================= ; Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ; Byte | | | | | | | | | ; ======================================================================= ; 0 |AdValid| Error Class | Error Code | ; ----------------------------------------------------------------------- ; 1 | Vendor Unique | Logical Block Address (MSB) | ; ----------------------------------------------------------------------- ; 2 | Logical Block Address | ; ----------------------------------------------------------------------- ; 3 | Logical Block Address (LSB) | ; ----------------------------------------------------------------------- LD A,(IX) AND 01111111b CP 70H ; Error Class 7? LD A,12 ; Bad Parameter SCF RET NZ ; No ; ; Extended Sense Data Format ; ; ======================================================================= ; Bit| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ; Byte | | | | | | | | | ; ======================================================================= ; 0 | Valid | Error Class (7) | Error Code (0) | ; ----------------------------------------------------------------------- ; 1 | Segment Number | ; ----------------------------------------------------------------------- ; 2 |Filemark| EOM | ILI |Reservd| Sense Key | ; ----------------------------------------------------------------------- ; 3 | Information Byte (MSB) | ; ----------------------------------------------------------------------- ; 4 | Information Byte | ; ----------------------------------------------------------------------- ; 5 | Information Byte | ; ----------------------------------------------------------------------- ; 6 | Information Byte (LSB) | ; ----------------------------------------------------------------------- ; 7 | Additional Sense Length (n) | ; ----------------------------------------------------------------------- ; 8 - | Additional Sense Bytes | ; n+7 | | ; ----------------------------------------------------------------------- LD A,(IX+12) ; Get Sense Code ; CP 0A0H ; Sense Code > 0a0h ? ; *M*v0.10 cp 2BH ; Sense Code > 2ah? ; *M* LD E,A JR NC,OutRange ; Yes ; LD HL,SnsTable ADD HL,DE LD A,(HL) OR A SCF RET P ; call Get_ID AND 20H RET NZ ; OutRange: LD A,12 ; Bad Parameter SCF RET ; Inquiry - 'Inquiry' (24h bytes) ; Input : A = ID ; HL = transfer address ; Output: A = error code ; A = 42h > error ; A = 85h > Ok ; ; 'Inquiry' data: ; Transfer address + 00h - Device Type Code ; + 01h - ; + ; ; Inquiry: PUSH AF ; ID LD A,03H OUT (REGSET),A LD A,INQUIR ; Inquiry command OUT (RDWREG),A POP AF PUSH AF AND 11100000b PUSH AF OUT (RDWREG),A ; Logical Unit Number LD C,RDWREG XOR A OUT (RDWREG),A ; Reserved OUT (RDWREG),A ; Reserved LD B,24H OUT (C),B ; Allocation Length - 24h bytes OUT (RDWREG),A JR J.5051 ; ModeSense - 'Mode Sense' (max. 128 bytes) ; Input : A = LUN + ID ; HL = transfer addres ; B = Page Control Field & Page Code ; ; bits 7 - 6 - 00b = Actual value ; 01b = Changeable value ; 10b = Default value ; 11b = vastgezette waarde ; bits 5 - 0 - page code ; ; Mode-Parameters for magnet discs ; ; 01h - Read/Write error ; 02h - Disconnect/Reconnect ; 03h - Format ; 04h - Non removable HDD-geometrie ; 05h - Floppy disc ; 07h - Verify-error ; 08h - Cache ; 09h - Peripheral ; 0Ah - Steuermodus-Seite ; 0Bh - Mediatype ; 0Ch - Notch ; Output: A = SCSI Status ; D = Target status ; E = Message ModeSense: PUSH AF ; ID LD A,3 OUT (REGSET),A LD A,MODSNS ; Mode Sense command OUT (RDWREG),A POP AF PUSH AF AND 11100000b PUSH AF OUT (RDWREG),A ; Logical Unit Number LD C,RDWREG OUT (C),B ; Page Code XOR A OUT (RDWREG),A ; Reserved LD B,128 OUT (C),B ; Allocation Length = 128 bytes OUT (RDWREG),A ; 0 JR J.5051 ; ReadCap - 'Read Capacity' ; Input : A = ID ; HL = transer address (8h bytes) ; Output: A = error code ; A = 42h > error ; A = 85h > Ok ; Read Capacity Data (8 bytes) ; transfer address + 00h - 03h -> # of sector on HDD (MSB - LSB) ; " " + 04h - 07h -> sector size (MSB - LSB) always 512 on HDD ReadCap: PUSH AF ; ID LD A,03H OUT (REGSET),A LD A,RDCAPAC ; Read Capacity command OUT (RDWREG),A POP AF PUSH AF AND 11100000b PUSH AF OUT (RDWREG),A ; Logical Unit Number LD C,RDWREG XOR A LD B,08H J$504B: OUT (RDWREG),A ; 8 * 0 DJNZ J$504B ; LD B,08H J.5051: LD A,0FH OUT (REGSET),A POP AF RLCA RLCA RLCA OUT (RDWREG),A ; Target LUN LD A,12H OUT (REGSET),A XOR A OUT (RDWREG),A ; Transfer count (MSB) OUT (RDWREG),A ; Transfer count OUT (C),B ; Transfer count (LSB) 8 bytes POP AF AND 07H OUT (RDWREG),A ; Destination ID ; C.506B: IN A,(AUXSTAT) ; Read Auxiliary Status OR A ; Interrupt Pending? JP P,J$507F ; No ; LD A,17H OUT (REGSET),A EX (SP),HL EX (SP),HL IN A,(RDWREG) ; Read SCSI status OR A ; Reset State ? CALL Z,SetWD3393 ; Yes ; JR C.506B J$507F: AND 00110000b ; BuSY? , Command In Progress ? JR NZ,C.506B ; Yes ; LD IX,RT_02 ; CIP_7: IN A,(AUXSTAT) AND 00010000b ; Command In Progress? JR NZ,CIP_7 ; Yes ; LD A,10H OUT (REGSET),A XOR A OUT (RDWREG),A ; Set Command Phase LD A,18H OUT (REGSET),A LD A,SelATNTrn OUT (RDWREG),A ; Select-with-!ATN and-Transfer LD A,19H OUT (REGSET),A ; Select data register CALL FastExec ; Read Capacity (or other) ; *** BEGMOV ReadCap *** J.50A3: IN A,(AUXSTAT) RRCA ; Data Buffer Ready ? JR NC,J$50B0 ; INI JR J.50A3 DEFB 0,0,0,0 ; Dummy J$50B0: AND 01000000b ; Interrupt Pending ? JR NZ,J$50B6 ; Yes ; JR J.50A3 ; *** ENDMOV ReadCap *** J$50B6: call TbrCPUres JP TermAct J.50BC: POP AF AND 7 OUT (RDWREG),A ; Destination ID Level2_CIP2: IN A,(AUXSTAT) ; Read Auxiliary Status OR A ; Interrupt Pending? JP P,J$50D5 ; No ; LD A,17H OUT (REGSET),A EX (SP),HL EX (SP),HL IN A,(RDWREG) ; Read SCSI status OR A ; Reset state? CALL Z,SetWD3393 ; Yes ; JR Level2_CIP2 J$50D5: AND 00110000b ; Level 2 Command In Progress? JR NZ,Level2_CIP2 ; Yes ; LD IX,RT_03 CIP_8: IN A,(AUXSTAT) AND 00010000b ; Command In Progress? JR NZ,CIP_8 ; Yes ; LD A,10H OUT (REGSET),A XOR A OUT (RDWREG),A ; Set Command Phase LD A,18H OUT (REGSET),A LD A,SelATNTrn ; Select-with-!ATN and-Transfer OUT (RDWREG),A LD A,19H OUT (REGSET),A ; Select data register CALL FastExec ; *** BEGMOV xxxxx *** J.50F9: IN A,(AUXSTAT) ; Read Auxiliary status RRCA ; Data Buffer Ready? JR NC,J$5106 ; No ; OUTI JR J.50F9 DEFB 0,0,0,0 ; Dummy J$5106: AND 01000000b ; Interrupt pending? JR NZ,IntP_3 ; Yes ; JR J.50F9 ; *** ENDMOV xxxxx *** IntP_3: call TbrCPUres JP TermAct ; RdDefect - Read Defecf Data ; Input : A = LUN + ID ; B = Plist, Glist and Defect List Format ; DE = Allocation length ; HL = Data address ; Output: A = SCSI Status ; D = Target Status ; E = Target msg ; Modify: RdDefect: push af ld a,3 out (REGSET),a ld a,RDEFDAT out (RDWREG),a pop af push af and 11100000b push af out (RDWREG),a ; Logical Unit Number ld c,RDWREG out (c),b ; PList, GList and Defect List Format xor a out (c),a ; Reserved out (c),a ; Reserved out (c),a ; Reserved out (c),a ; Reserved out (c),d ; Allocation length (MSB) out (c),e ; Allocation length (LSB) out (c),a fill_regs: ld a,0fh out (REGSET),a pop af ; Target LUN rlca rlca rlca out (c),a ld a,12h out (REGSET),a xor a out (c),a ; Transfer count (MSB) out (c),d ; Transfer count (2ND) out (c),e ; Transfer count (LSB) pop af and 7 out (c),a ; Destination ID jp C.506B ; Execute command ; Copy - SCSI COPY function ; Input : A = LUN + ID ; DE = Parameter List length ; HL = data address ; Output: A = SCSI Status ; D = Target Status ; E = Target message ; Modify: Copy: push af ld a,3 out (REGSET),a ld a,COPY_ out (RDWREG),a ; Copy command pop af push af and 11100000b push af out (RDWREG),a ; Logical Unit Number ld c,RDWREG xor a out (c),a ; Parameter List Length (MSB) out (c),d ; Parameter List Length out (c),e ; Parameter List Length (LSB) out (c),a ; 0 jr fill_regs ; MedRemoval - PREVENT ALLOW MEDIUM REMOVAL ; Input : A = LUN + ID ; B = 0 = Prevent disabled, 1 = Prevent enabled ; Output: A = SCSI Status ; D = Target Status ; E = Target message ; Modify: MedRemoval: push af ld a,3 out (REGSET),a ld a,MEDREM out (RDWREG),a ; PREVENT ALLOW MEDIUM REMOVAL command pop af push af and 11100000b push af out (RDWREG),a ; Logical Unit Number ld c,RDWREG xor a out (c),a ; Reserved out (c),a ; Reserved out (c),b ; Prevent out (c),a ; Control jp J$4C5A ; TermAct - Terminate (HDD) Actions ; Output: D = Target Status, E = message, A = SCSI status TermAct: ; Terminate Actions MAK 3.0 LD DE,0008h ; D = 0 status GOOD ; , E = 8 NO OPERATION msg LD C,RDWREG TermLp: IN A,(AUXSTAT) BIT 0,A ; Data Buffer Ready? JP NZ,Jx4BBD ; Yes ; BIT 5,A ; BuSY? JR NZ,TermLp ; Yes ; LD A,17H OUT (REGSET),A nop nop IN A,(RDWREG) ; Read SCSI status ; Filter possible bug in the WD33C93A cp 4 jr nz,no4bug res 2,a no4bug: BIT 3,A ; MCI contains new SCSI bus phase? JR NZ,GetNwPh ; Yes ; CP 16H ; A Select-and-Transfer cmd compl succ? JP Z,Jx4BB4 ; Yes ; BIT 4,A ; Successful Completion Interrupt? RET NZ ; Yes ; OR A ; Reset state ; JP Z,Cx4BC3 ; Yes jp z,SetWD3393 ; CP 21H ; Save Data Pointer? JR NZ,Jx4AFC ; No ; PUSH HL POP IY DEC A Jx4AFC: CP 20H ; Message ready JP Z,Jx4B9C ; Yes ; CP 85H ; Disconnect occurred? JR NZ,Jx4B0A ; No ; BIT 7,D ; Service Required Interrupt? RET Z ; No ; JR TermLp ; ; ----------------- Jx4B0A: CP 80H ; Reselected? JR NZ,Jx4B12 ; No ; RES 7,D JR TermLp ; ; ----------------- Jx4B12: BIT 6,A ; Terminated Interrupt? JR NZ,Jx4B18 ; No ; OUT (HARDWR),A ; Reset WD3393 Jx4B18: LD D,02H ; D = 2, CHECK CONDITION RET ; GetNwPh: AND 07H LD B,A LD A,18H OUT (REGSET),A LD A,TransInfo+128 ; Transfer Info (one single byte) OUT (RDWREG),A Jx4B26: IN A,(AUXSTAT) RRCA ; Data Buffer Ready? JR NC,Jx4B26 ; No ; LD A,19H OUT (REGSET),A ; Select Data register INC B DJNZ Jx4B36 ; RT_03: Ix4B32: OUTI ; Data Out Phase call RT_01 jp TermLp ; ; ----------------- Jx4B36: DJNZ Jx4B3D ; RT_02: Ix4B38: INI ; Data In Phase call RT_01 JP TermLp ; ; ----------------- Jx4B3D: DJNZ Jx4B44 ; Jx4B3F: XOR A ; Command Phase OUT (RDWREG),A jp TermLp ; ; ----------------- Jx4B44: DJNZ Jx4B4A ; IN D,(C) ; Status Phase jp TermLp ; ; ----------------- Jx4B4A: DJNZ Jx4B4F ; JP Jx4B3F ; Unspecified Info Out Phase ; ; ----------------- Jx4B4F: DJNZ Jx4B56 ; IN A,(RDWREG) ; Unspecified Info In Phase JP TermLp ; ; ----------------- Jx4B56: DJNZ Jx4B5F ; OUT (C),E ; Message Out Phase LD E,08H JP TermLp ; ; ----------------- Jx4B5F: IN A,(C) ; Message In Phase JP Z,TermLp ; Command Complete msg ; JP M,TermLp ; Identify ; CP 02H ; Save Data Pointers? JR Z,Jx4B90 ; Yes ; CP 03h ; Restore Pointers? JR Z,Jx4B96 ; Yes ; CP 04h ; Disconnect? JR Z,Jx4B85 ; Yes ; CP 07h ; Message Reject? JR Z,Jx4B8A ; Yes ; CP 08h ; No Operation? JP Z,TermLp ; Yes ; CP 09H ; Message Parity Error? JR Z,Jx4B8A ; Yes ; LD E,07H ; Message Reject JP TermLp ; ; ----------------- Jx4B85: SET 7,D ; Service Required Interrupt JP TermLp ; ; ----------------- Jx4B8A: LD DE,0206h ; D = Check Condition, E = Abort JP TermLp ; ; ----------------- Jx4B90: PUSH HL POP IX JP TermLp ; ; ----------------- Jx4B96: PUSH IX POP HL JP TermLp ; ; ----------------- Jx4B9C: LD A,E CP 08H ; No Operation? JR Z,Jx4BA9 ; Yes ; LD A,18H OUT (REGSET),A LD A,02H ; Issue Assert ATN cmd OUT (RDWREG),A Jx4BA9: LD A,18H OUT (REGSET),A LD A,03H ; Issue Negate ACK cmd OUT (RDWREG),A JP TermLp ; ; ----------------- Jx4BB4: LD A,0FH OUT (REGSET),A ; Select Target LUN register IN D,(C) ; Read Target Status JP TermLp ; ; ----------------- Jx4BBD: CALL 0F398h ; JP (IX) ; JP TermLp ; SetWD3393 - Set host ID, Timeout etc. SetWD3393: xor a OUT (REGSET),A EX (SP),HL EX (SP),HL IN A,(RDWREG) OR A ; Own ID = 0 ? JR NZ,J$4B7B ; No ; OUT (REGSET),A call Get_ID ; A = 10110000b CPL ; A = 01001111b AND 07H ; A = 00000111b OUT (RDWREG),A ; Set Own ID to 7 ; Avanced Features disabled ; No Host Parity checking ; Select divisor CIP_2: IN A,(AUXSTAT) AND 00010000b ; Command In Progress? JR NZ,CIP_2 ; Yes ; LD A,18H OUT (REGSET),A XOR A OUT (RDWREG),A ; Execute R