; MDS-800 I/O Drivers for CP/M 2.2 ; (four drive single density version) ; ; Version 2.2 February, 1980 ; vers equ 22 ;version 2.2 ; ; Copyright (c) 1980 ; Digital Research ; Box 579, Pacific Grove ; California, 93950 ; ; true equ 0ffffh ;value of "true" false equ not true ;"false" test equ false ;true if test bios ; if test bias equ 03400h ;base of CCP in test system endif if not test bias equ 0000h ;generate relocatable cp/m system endif ; patch equ 1600h ; org patch cpmb equ $-patch ;base of cpm console processor bdos equ 806h+cpmb ;basic dos (resident portion) cpml equ $-cpmb ;length (in bytes) of cpm system nsects equ cpml/128 ;number of sectors to load offset equ 2 ;number of disk tracks used by cp/m cdisk equ 0004h ;address of last logged disk on warm start buff equ 0080h ;default buffer address retry equ 10 ;max retries on disk i/o before error ; ; perform following functions ; boot cold start ; wboot warm start (save i/o byte) ; (boot and wboot are the same for mds) ; const console status ; reg-a = 00 if no character ready ; reg-a = ff if character ready ; conin console character in (result in reg-a) ; conout console character out (char in reg-c) ; list list out (char in reg-c) ; punch punch out (char in reg-c) ; reader paper tape reader in (result to reg-a) ; home move to track 00 ; ; (the following calls set-up the io parameter block for the ; mds, which is used to perform subsequent reads and writes) ; seldsk select disk given by reg-c (0,1,2...) ; settrk set track address (0,...76) for subsequent read/write ; setsec set sector address (1,...,26) for subsequent read/write ; setdma set subsequent dma address (initially 80h) ; ; (read and write assume previous calls to set up the io parameters) ; read read track/sector to preset dma address ; write write track/sector from preset dma address ; ; jump vector for indiviual routines jmp boot wboote: jmp wboot jmp const jmp conin jmp conout jmp list jmp punch jmp reader jmp home jmp seldsk jmp settrk jmp setsec jmp setdma jmp read jmp write jmp listst ;list status jmp sectran ; maclib diskdef ;load the disk definition library disks 4 ;four disks diskdef 0,1,26,6,1024,243,64,64,offset diskdef 1,0 diskdef 2,0 diskdef 3,0 ; endef occurs at end of assembly ; ; end of controller - independent code, the remaining subroutines ; are tailored to the particular operating environment, and must ; be altered for any system which differs from the intel mds. ; ; the following code assumes the mds monitor exists at 0f800h ; and uses the i/o subroutines within the monitor ; ; we also assume the mds system has four disk drives revrt equ 0fdh ;interrupt revert port intc equ 0fch ;interrupt mask port icon equ 0f3h ;interrupt control port inte equ 0111$1110b ;enable rst 0(warm boot), rst 7 (monitor) ; ; mds monitor equates mon80 equ 0f800h ;mds monitor rmon80 equ 0ff0fh ;restart mon80 (boot error) ci equ 0f803h ;console character to reg-a ri equ 0f806h ;reader in to reg-a co equ 0f809h ;console char from c to console out po equ 0f80ch ;punch char from c to punch device lo equ 0f80fh ;list from c to list device csts equ 0f812h ;console status 00/ff to register a ; ; disk ports and commands base equ 78h ;base of disk command io ports dstat equ base ;disk status (input) rtype equ base+1 ;result type (input) rbyte equ base+3 ;result byte (input) ; ilow equ base+1 ;iopb low address (output) ihigh equ base+2 ;iopb high address (output) ; readf equ 4h ;read function writf equ 6h ;write function recal equ 3h ;recalibrate drive iordy equ 4h ;i/o finished mask cr equ 0dh ;carriage return lf equ 0ah ;line feed ; signon: ;signon message: xxk cp/m vers y.y db cr,lf,lf if test db '32' ;32k example bios endif if not test db '00' ;memory size filled by relocator endif db 'k CP/M vers ' db vers/10+'0','.',vers mod 10+'0' db cr,lf,0 ; boot: ;print signon message and go to ccp ; (note: mds boot initialized iobyte at 0003h) lxi sp,buff+80h lxi h,signon call prmsg ;print message xra a ;clear accumulator sta cdisk ;set initially to disk a jmp gocpm ;go to cp/m ; ; wboot:; loader on track 0, sector 1, which will be skipped for warm ; read cp/m from disk - assuming there is a 128 byte cold start ; start. ; lxi sp,buff ;using dma - thus 80 thru ff available for stack ; mvi c,retry ;max retries push b wboot0: ;enter here on error retries lxi b,cpmb ;set dma address to start of disk system call setdma mvi c,0 ;boot from drive 0 call seldsk mvi c,0 call settrk ;start with track 0 mvi c,2 ;start reading sector 2 call setsec ; ; read sectors, count nsects to zero pop b ;10-error count mvi b,nsects rdsec: ;read next sector push b ;save sector count call read jnz booterr ;retry if errors occur lhld iod ;increment dma address lxi d,128 ;sector size dad d ;incremented dma address in hl mov b,h mov c,l ;ready for call to set dma call setdma lda ios ;sector number just read cpi 26 ;read last sector? jc rd1 ; must be sector 26, zero and go to next track lda iot ;get track to register a inr a mov c,a ;ready for call call settrk xra a ;clear sector number rd1: inr a ;to next sector mov c,a ;ready for call call setsec pop b ;recall sector count dcr b ;done? jnz rdsec ; ; done with the load, reset default buffer address gocpm: ;(enter here from cold start boot) ; enable rst0 and rst7 di mvi a,12h ;initialize command out revrt xra a out intc ;cleared mvi a,inte ;rst0 and rst7 bits on out intc xra a out icon ;interrupt control ; ; set default buffer address to 80h lxi b,buff call setdma ; ; reset monitor entry points mvi a,jmp sta 0 lxi h,wboote shld 1 ;jmp wboot at location 00 sta 5 lxi h,bdos shld 6 ;jmp bdos at location 5 if not test sta 7*8 ;jmp to mon80 (may have been changed by ddt) lxi h,mon80 shld 7*8+1 endif ; leave iobyte set ; previously selected disk was b, send parameter to cpm lda cdisk ;last logged disk number mov c,a ;send to ccp to log it in ei jmp cpmb ; ; error condition occurred, print message and retry booterr: pop b ;recall counts dcr c jz booter0 ; try again push b jmp wboot0 ; booter0: ; otherwise too many retries lxi h,bootmsg call prmsg jmp rmon80 ;mds hardware monitor ; bootmsg: db '?boot',0 ; ; const: ;console status to reg-a ; (exactly the same as mds call) jmp csts ; conin: ;console character to reg-a call ci ani 7fh ;remove parity bit ret ; conout: ;console character from c to console out jmp co ; list: ;list device out ; (exactly the same as mds call) jmp lo ; listst: ;return list status xra a ret ;always not ready ; punch: ;punch device out ; (exactly the same as mds call) jmp po ; reader: ;reader character in to reg-a ; (exactly the same as mds call) jmp ri ; home: ;move to home position ; treat as track 00 seek mvi c,0 jmp settrk ; seldsk: ;select disk given by register c lxi h,0000h ;return 0000 if error mov a,c cpi ndisks ;too large? rnc ;leave HL = 0000 ; ani 10b ;00 00 for drive 0,1 and 10 10 for drive 2,3 sta dbank ;to select drive bank mov a,c ;00, 01, 10, 11 ani 1b ;mds has 0,1 at 78, 2,3 at 88 ora a ;result 00? jz setdrive mvi a,00110000b ;selects drive 1 in bank setdrive: mov b,a ;save the function lxi h,iof ;io function mov a,m ani 11001111b ;mask out disk number ora b ;mask in new disk number mov m,a ;save it in iopb mov l,c mvi h,0 ;HL=disk number dad h ;*2 dad h ;*4 dad h ;*8 dad h ;*16 lxi d,dpbase dad d ;HL=disk header table address ret ; ; settrk: ;set track address given by c lxi h,iot mov m,c ret ; setsec: ;set sector number given by c lxi h,ios mov m,c ret sectran: ;translate sector bc using table at de mvi b,0 ;double precision sector number in BC xchg ;translate table address to HL dad b ;translate(sector) address mov a,m ;translated sector number to A sta ios mov l,a ;return sector number in ÍÕÆNO SPACEÍ^ :ðõÍTÍéÂy!ÍÝÍB*ˆëÍOþ=Ê?þ_Âsë#"ˆÍ^ÂsñG!ð~·ÊY¸pÂsp¯2ÍÍéÊmÍÍÆÍêÆÍfà ‚ͧÆFILE EXISTSÍøþÒ _:Îþ Ê ÍÉÍõ:Îþ ÂÄ:ð·Ê‰=2ïÍ)ͽÉÖþ  ÕÍTÑ!ƒÍ@ÍÐÊk!åëÍØÍÍùÂá€}“|šÒqÃáá=ÂqÍfÍ^!ðå~2Í>Í`á~2ݯ2í\!Í!ÍB!~·Ê>þ Ê>#Ã0�~·ÊO#ÃCx2€Í˜ÍÕÍÍ1«Í)ͽÂÍfà zͧÆBAD LOADCOMÍfÍ^:ÎÖ !ð¶Â Â$$$ SUB"Ù¥«±ë"C ë{2Ö!"E 9" 1A ¯2à2Þ!tåyþ)ÐK!G_^#V*C ëéÈ � Î Ô í ó ø á þ ~ƒEœ¥«È×àæìõþ , &-AGMS  ›!ÊÍåþÊÉ!Õô!áô!ÜÍåÃBdos Err On : $Bad Sector$Select$File R/O$åÍÉ :B ÆA2ƺÍÓ ÁÍÓ ! ~6·Àà ÍûÍ ØõOÍ� ñÉþ Èþ Èþ ÈþÈþ É: ·ÂE ÍæÈÍ þÂB Í þʯÉ2 >É: ·Âb ÅÍ# ÁÅÍ ÁÅ: ·ÄÁy! þÈ4þ Ð5~·ÈyþÂy 5Éþ À6ÉyÍ Ò� õ^ÍH ñö@Oyþ ÂH  ÍH : æ– Éͬ  Í à #ÍH ÍÉ : ! ¾Ð ÍH ù  ÍH  ÃH þ$ÈÅOÍ� ÁÃÓ : 2 *C N#åÅåÍûæáÁþ ÊÁ þ ÊÁ þ x·Êï : 2 Ãp þÂ& x·Êï ~+é þÂ7 ÅåÍÉ ¯2 Ãñ þÂH å! >–wáÃï þÂ_ á: ! ¾Òá 5ͤ ÃN þÂk ͱ áÃá þ¦ Åͱ ÁáåÅx·ÊŠ #NÅåÍ áÁÃx å: ·Êñ ! –2 ͤ ! 5™ Ãñ #wÅåOÍ áÁ~þx½ þʹÚï áp ÃH Í Ã Íà y<Êà <Êà Í·Ê‘Í Ã :à !qÉëMDÃÓ Í# 2E É>à ! ^#Vëé Èw#ÃP :B OÍ|µÈ^#V#"³##"µ##"·##ë"Ð!¹ÍO *»ë!ÁÍO *Æ|!Ý6ÿ·Ê� 6>ÿ·Éͯ*µw#w*·w#wÉÍ'û Í*·È! ÃJ *êÍê "å"ì!åN#F*·^#V*µ~#foy“xšÒú å*Á{•_zœWá+Ãä å*ÁÚ y•xœÚ ëá#Ãú áÅÕåë*ÎDMÍÑ*µs#rÑ*·s#rÁy“OxšG*ÐëÍ0MDÃ!!ÃN:ã· ÂE G>–O:â Ê\ ·ÃS €É*C  :Ý·Êq n&É ^#VëÉÍ> OÍ^ "åÉ*å}´É:Ã*å)=Â� "ç:ÄO:㡵o"åÉ*C  É*C ë!ÉÍ® ~2ãë~2áͦ :Ŧ2âÉÍ® :ÕþÂÞ ¯O:ã�wë:áwÉ È|·g}oÃë €*¹¯†# Âý É È)à Å:B O!Í Áyµox´gÉ*­:B OÍê }æÉ!­N#FÍ "­*È#ë*³s#rÉÍ^  ~Ð!ÃJ Í È! ÃJ *¹:é…oÐ$É*C ~ÉÍi 6ÉÍi ö€wÉ*êë*³{–#zžÉÍ Ør+sÉ{•ozœgÉÿ*ìë*ÌÍ• ÐÅÍ÷ *½ë*ìÁ ÊÄ ¾ÈÍ ÐÍ, ÉwÉÍœ Íà ͸ ÃÚ Íà Ͳ !±Ãã !¹N#FÃ$*¹ë*±€ÃO !ê~#¾À<É!ÿÿ"êÉ*Èë*ê#"êÍ• ÒÃþ :êæ‡ 2é·ÀÅÍà ÍÔ ÁÞ yæ<_WyæOx‡‡‡‡‡±OxæG*¿ ~ÂVÉÕÍ5æþÁ±ÂdwÉÍ^ ÅÑ ÈÕ:ݷʈÅåNÃŽ ÅN#Fåy°Ê�*Æ}‘|˜Ô\á#ÁÃu*ÆÍê #DM*¿6# x±Â±*Êë*¿s#rÍ¡ *³6#6Íþ ÿÍÍõ ÈÍ^ >å¾ÊÒ:A ¾Âö#~Ö$Âö=2E ÍkÍŒ ÃÒ:Ôà Åõ:Å/Gy Oñ ‘æÁÉ>ÿ2Ô!Øq*C "ÙÍþ Í¡ ÍÍõ Ê”*ÙëþåÊJÕÍ ÑÒ”Í^ :ØOy·Êƒþ?Ê|xþ Ê|þ Ês–æÂ-Ã|ÅNÍÁÂ-# ÃS:êæ2E !Ô~ЯwÉÍþ >ÿà ÍT  ÍÍõ ÈÍD Í^ 6åÍkÍÆ Í-äPYy°ÊÑ ÕÅÍ5ÒìÁÑ*Æ{•zœÒôÅÕBKÍ5ÒìÑÁÃÀ<ÍdáÑÉy°ÂÀ!É Õ*C ëÍ^ ÁÍO ÍÃ ÃÆ ÍT  Í*C ~wÍõ ÈÍD  ÍÍ-Ã' ÍÍõ È ÍÍ-Ã@ÍÍõ Èͦ ~õåÍ^ ë*C  ÕÍO Íx Ñ! N!Fáñwy¾xÊ‹>Ú‹>€*C wÉ~#¶+Àw#w+ɯ2E 2ê2ëÍ ÀÍi æ€ÀÍÍõ ÈÍ^ ë*C :Ý·Êè~·ÂÛw·Âá~¾ÂÃýÍ”ëÍ”ë¾Â#¾Â # ÂÍìÿ ë ¾Úw ë ~>ÿ2ÒÃ!E 5ÉÍT *C å!¬"C ÍÍõ á"C Èë!¯w# ÂF! wÍŒ ÍýÃx ¯2ÒÍ¢Íõ È*C  ~<æwʃG:Å !Ҧʎì 4~æʶÍÍõ ¬:Ó<ʶÍ$Íõ ʶïÍZÍ» ¯Ã Í Ãx >2Õ>ÿ2ÓÍ» :ã!á¾Úæþ€ÂûÍZ¯2ã:E ·ÂûÍw Í„ ÊûÍŠ ÍÑ Í² ÃÒ Ã >2Õ>2ÓÍT *C ÍG Í» :ãþ€Ò Íw Í„ ÂnÍ> 2×·Ê;O Í^ DM;}´ÂH>à "åë*C  :Ý·:×ÊdÍd sÃlO s#r:E ·ÀÅÍŠ :Õ==»ÁÅy==»å*¹Ww#òŒÍà *ç"åÅÍÑ Á͸ *å:ÄG¥¸#šá"åÍÚ ÍÑ ÁÅ͸ Á:ã!á¾ÚÒw4!õÍi æwñþÂ:ÕþÂÍÒ ÍZ!E ~·Âþ=2ã6ÃÒ ¯2ÕÅ*C ë!!~æõ~#~æO~æGñ#n,-.‹! w! y–ÂG!x–æÊÅÕÍ¢ÑÁ.:E <Ê„! q!pÍQ:E <ÂÁÅ. Ê„Í$.:E <Ê„Á¯Ã åÍi 6ÀáÁ}2E Ãx ÿÍÌÁÉÍÌÉëN! ~æ€�O>ˆG~æ€G!~‡‡‡‡õ€Gõá}áµæÉ Í*C !år#r#rÍõ Ê Í^ Í¥áå_y–#xž#{žÚs+p+qÍ-ÃäáÉ*C  Í¥!!q#p#wÉ*¯:B OÍê åëÍY áÌG }Ø*¯MDÍ "¯ã:Ö!B ¾ÈwÃ!>ÿ2Þ*C ~æ=2ÖþÒu:B 2ß~2àæàwÍE:A *C ¶wÉ>"à !"­"¯¯2B !€"±ÍÚ Ã!Ír ÍQÃQÍQâë~þ?ÊÂͦ ~þ?Är ÍQÍÃé *Ù"C ÍQÍ-Ãé ÍQÍœÃÍQüÍQÃþÍr ÍQÃ$ÍQÍÃ*¯Ã):B à ë"±ÃÚ *¿Ã)*­Ã)ÍQÍ;Ã*»"E É:ÖþÿÂ;:A à æ2A ÉÍQÓÍQÜÍQÃÒ*C }/_|/*¯¤W}£_*­ë"¯}£o|¢g"­É:Þ·Ê‘*C 6:à·Ê‘w:ß2ÖÍE* ù*E }DÉÍQ>2ÕÍÌÉå€Ã+%Ã9È#Ãp#Ã|#è#Ã$Ãê#Ã`ÃrÃÕÃÛÃáÃçÃïó#ÃùÃàÃ1>2™Í<€Íá>Ã22!"!"¯2I(2m2E(:™·!�Êu!Ÿ^#VÃ2!Ú"ísúvv!P(í°Ã€ëí°ëÉ7£­š2£*>(|æ€O|æg+Ê+·|g}oÃ#|±g"C(:þÂe!P"�ͺ:A(ÆG>Í:=(æðG>ÍÍZÃ|!@(F(Ê|¾#ÊmÍØ:>(=æo&)))))))8$ë*<(:þ¢|æö`g>§ÂÂÍè:þÊ·:E(É!8$"�ÍݯÉëÍè:þÊ·>2m>=>ÀÍlÉ!ë@í°Ã@&.""á1é<i`É!ÉS(-ô) ÀͺÍQ! í°ÍÝÉ>Í<ÍÉ:m·Âk¯2I(ÍÕÉy2@(þÒÿ{æ¶a.ÍÏ|µÊÿåÍÈÑs#r#q#~·Ì(ëy2¯ ʬöâ2�:@(2O(Éa.ÍÏÍÈ^#V#NëÃ�:@(_!óÉ`i"A(É`i">(É`i"<(ɯ28(Í Éy2Ô>Í É:@(g.ÍÏÉÍlØ@(!F(Íë:£·Êc:Ô·ÂD:8(·Ê^*çë*9(z¼ÂZ{½ÂZ!@(:;(¾ÂZÉ=ÊZ*ç"9(:@(2;(>28(ɯ28(:=È>2¦ÍyÉ>·È> 2¦ÍyÉÍ{ó¯2m Å.ÍË*K(DM.ÍË*M(DM.ÍË8$.ÍË.ÍËÁ>ÒÇ7>ÿÊÇxþƒÅ.ÍËÁÃ2E(É:F(gÕÅå|¥Oogy–ÒÖ#Ñ{_~#foyÁÑé~#·ÈåOÍ áÃò!:æO:@(¹À:O(O:æð±2É!Éo&))))É6ÅÕ:@(g. ÍÏ|µÊo^#V#ë"A(ë~#fo"C(ÍØ*ñ8$·Êl~<Êr:@(w#ÍëÃT"ñÑÁÉ!ÛÍòÃo!Ó(:F(Oë*ñëz¼Âž{½Âž*G("K(*I("M(Éåy¾ÂÓ#:G(¾ÂÓ#:H(¾ÂÓ#:I(¾ÂÓ#:J(¾ÂÓ#K(ëÅÍëÁáÉá  BAD MAP OVERFLOW! Ó(