IMD 1.12: 12/12/2009 20:06:20 Morrows M-16 IBIOS development disk  13!x>w>>wwyWw yA yH->t>c>t>rw#e/v\X COPYRIGHT (C) 1979, DIGITAL RESEARCH _͌> ͒> Ò> Ò͘~#͌ì _2<į2 Ň!˶2:2a{_:˷ʖ:˷>Ľʖ:=2–!B!6#5ʖ:Ľ!ͬʧ )!F#xʺ~0wëw!" !~6ͽ:ý(!#͘*~ "Ʒ"͌#>?͌͘ =_.:;<> Oƅo$>!Y2*O"ʉ@G:ʐ:wÖx2p0ʹ#*©6?ëw˜0ï#6 ¹.0#*6?w0#6 #6" #~?  xDIR ERA TYPESAVEREN USER !yO#< Ty#O 3ǯ21y_͸2y2ͽ:ķ1͘A͌>>͌92^ :˷¥.!_~#fow]ɭʎʥ!v"!çREAD ERRORçNO FILE^:˷ ! ~ 3#0 Wx x ƀ Ƃ G ~ # 3x~#B!Y~ɯ2:˷=!˾ý:˷=!˾:ý^T!~  6?#ˆ:`O> K{͘A͒>:͒͢>:͒͢xK > K > ͒x  ͢ØÆ^ BRͧ9!5‚#~Y‚#"T<ÆALL (Y/N)?^ Tʧ͘!6!~ڇ ɯw4!Y~ʆ͌†t=ʆf ^ T ɯ2o&)|+!<ͧÆNO SPACE^ :Ty!B*O=?_s#"^sG!~Yʸpsp2mÆÆf ͧFILE EXISTS _: É: :˷ʉ=2)ͽÉ T!@k!}|q=qf^!~2>`~2˯2\!!B!~> >#0~O#Cx2͘1)ͽÂf zͧÆBAD LOADCOMf^: !˶ Â$$$ SUB ̙̥̫̱"C{2!"E9"1Aϯ22!ty)K!G_^#V*Cΐ~؃E؜إث ,&-AGMSϛ!!ô!ô!Bdos Err On : $Bad Sector$Select$File R/O$:BA2!~6 O͐  :ϷE B 2>: Ϸb# : Ϸy! 4 5~yy5 6yҐ^H@Oy H H: –ͬ  #H: ! Ͼ Hù H H $O͐: 2 *CN# x: 2 p&x~+é7ͯ2 H! >w_: ! Ͼ5ͤNkͱ¦ͱxʊ#Nx: Ϸ! ϖ2 ͤ! 5™#wO~x½p Hy<< ڷʑ :!qMD#2E>! ^#V w#P:BO|^#V#"##"##"##"!O*!O*|!6ʝ6>گ*w#w*w#w'û*ڷ! J*""!N#F*^#V*~#foyx*{_zW+*yx#*DM*s#r*s#ryOxG*0MD!!N:ٷ EG>O: \зSЀ*C :ٷqn& ^#V>O^ "*}:*)=":O:١o"*C *C!ͮ~2~2ͦ:٦2ͮ:ЯO:فw:w |g}o*ٯ#  ):BO!yoxg*:BO}!N#F "*#*s#r^ ~!J! J*:مo$*C~i6iw**{#zr+s{ozg**͕** Ѿ,w͜͸Ͳ!!N#F$**O!~#:AϾ#~$=2Ek͌::/GyO>2!q*C"͡ʔ*JҔ^:Oyʃ?|x | sӖ-|N-# S:2E!~Яw>T D^6k-äPYy 5*{zBK5ڋ>*Cw~#+w#w+ɯ2E22i^ *C :ٷ~w~͔͔# #  w ~>2!E5T*C!"C"C!w# F! w͌xѯ2͢*C ~<wʃG:٠!٦ʎì 4~ʶ¬:<ʶ$ʶïZͻЯx>2>2ͻ:!پZկ2:EϷẅ́͊Ͳ>2>2T*CGͻ:ẅ́n>2;O ^DM;}H>"*C :ٷ:ddslO s#r:EϷ͊:==»y==»*Ww#*"͸*:G#š"͸:!پw4 iw:Z!E~=26Я2*C!!~~#~O~G#n,-.‹! w! yG!x͢.:E<ʄ! q!pQ:E<. ʄ$.:E<ʄi6}2ExN! ~态O>G~G!~G} *C!r#r#r ^ͥ_y#x#{s+p+q-*C ͥ!!q#p#w*:BOYG}*MD "ã:!BϾw!>2*C~=2u:B2~2wE:A*C϶w>"!""ٯ2B!"!rQQQâ~?ͦ~?rQ*"CQ-Q͜QüQrQ$Q*):B"*)*)Q;*"E:;:A2AQÓQÜQ*C}/_|/*٤W}_*"}o|g":ٷʑ*C6:ٷʑw:2E**E}DQ>2ÃÒ`;ÿ:QHKiro*eۂi|Zi|ZJ+?     12>>>!w~56K CP/M 2.2 EE 07/10/8>yx>>125:,!z z2324"@r!"@.6#6#6#w#N#6#6#6C> ͉q.3.4&q!y25i)))): n`i"@C> 2Z͉:3w> :4*@ error in track:3 sector:4> :Z=2Z|,Retry or Ignore`_OI w> 8w#-~#8:5/͉~ Uܷ͒`:uuzÁÁ>:57o&:ݠܠܩܲ>/>/>>/ܷ͒`¿N~#Ɛ'@'O: y> y_~#fo> >yO \ p>>*ݷQy!94~9pCw 29 PIP COM: IBIOS ASM IBIOS ASM !"#$%&'()IBIOS ASM*+,-./0123456789$DESTINATION IS R/O, DELETE (Y/N)?$**NOT DELETED**$$$$$$$NOT FOUND$COPYING -$REQUIRES CP/M 2.0 OR NEWER FOR OPERATION.$UNRECOGNI COPYRIGHT (C) 1979, DIGITAL RESEARCH, PIP VERS 1.5$$$ SUB =.:,<> _[]INPIRDPTRUR1UR2RDROUTLPTUL1PRNLSTPTPUP1UP2PUIBIOS ASM:;<=>?@ABCDEFGHIIBIOS ASMJKLMNOPQRSTUVWXYIBIOS ASMZ[\]^_`abcdefghiIBIOS ASMjklmZED DESTINATION$CANNOT WRITE$INVALID PIP FORMAT$CANNOT READ$INVALID SEPARATOR$1 :2L> ̈́M9 NTTYCRTUC1CONNULEOFDISK READ ERROR$DISK WRITE ERROR$VERIFY ERROR$NOT A CHARACTER SINK$READER STOPPING $NOT A CHARACTER SOURCE$IBIOS BAKnopqrstuvwxyIBIOS BAKMAKEPRL COMz{|}~MAKEPRL COM?221@:2!o6+6+6!6#6!6#6:G*o .!N6:^*M^!K6!6!6+6' :$ABORTED$BAD PARAMETER$INVALID USER NUMBER$RECORD TOO LONG$INVALID DIGIT$END OF FILE, CTL-Z?$CHECKSUM ERROR$CORRECT ERROR, TYPE RSTAT COM)IBIOS BAKIBIOS BAKIBIOS BAK(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)::=2K  :ʤ\:ҷ\x'Ͳ:!\͢  :͈'! ETURN OR CTL-Z$INVALID FORMAT$HEX$$$$NO DIRECTORY SPACE$NO FILE$COM$START NOT FOUND$QUIT NOT FOUND$CANNOT CLOSE DESTINATION FILEIBIOS BAKIBIOS BAK(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE)(INP:/OUT:SPACE) :$: $͈Ͳ!N6' :!Cwͯ !6:^͢c!6{:/>!/H{ͯ :<26à  !6 à  !60à  *& !6  !6  !6  *& . 1 4 7 : = F P [ f q  2yʭ :yʗ ͯ *"*6:2x÷ *"!x4d !"/ !j}=2| !"*KM^'_ !z6:|!z1 **M:>!(:=2%> >>!F!5+N! ~2!4<2T>>!b}*bMͭz:b2!b6:<2é>!!p+q*2!p+q*22!p+q*!p+q*!p+q*!p+q*2!p+q*/H:_2:!q:A/>Z!/H8: 2::=O>m:W!Q} Hmd>9>!6:2*M!EŠ ::=HҮͯ !6:Ҿ:2 !6::/H͈;!6:> !/> :2!q: " *M n :c4 *M n :2!c:Q !c:2: !:cw>!n !5 Y : { !6!q "}*}DM͆ ' ͯ *"!z4 :e !"͆ !z6:|!z '? 2*H#"H!{6:{ր!Ң *{&`ҥ*`MͭҞ!`6!6> :é:(!q:!wO! ~2*& :w>!:!4!6>:N<2N!!p+q* !q*& *M *M !p+q*!!p+q*"!p+q*$!6  ^#V͎ڗO **~2*#"m2m͖ 2m!6m!6m!6 m2mHHͯ :^!w:<2:0}:@E}:!S!W6: z!]6:cm!c6:_z!_6l:!lwҙ  â :0O !q:O| :O| !6:]2l:o'2o:n'2n:m'2m*mMͣ *nMͣ *oMͣ :] :{4 2!{4m *":ڹ ͯ !z4I '2!"!q: !4>!S :S! :2*M> *N& N2 !p+q!6!6+6 !6: S: M!6g8:N2M*M8p!6!6!6>! !kp+q*j> >ڪ Þ !qp+q/ *pDM9: :M2r:N!r !:r *r& N!r4 !6:ͯ m!62m!62m!62m!62m'2:2:TҒ:2 ::,: HHҰͯ : 2ó:E:1:2v!q!*8!*6: >:   *}2D" * * *&"!q:UY: Y:ҩ: ʩ:_2ʘ:€!6<! ^#V͎ * :w*#" = = = = = ͯ  *M !6q  !6q  !6q  *& !ڕ*&P 6!4z!6!6#6#6!6*M8:ھ:*͇g2ê::¿::,͡A<2O>͔: :ͳ.!ws+p+q+p+q:w=2wN *s*u w*s#"s*u#"u' !"*M^7 !x6:!xھ **DM͆ !6*ME:2::Ҳ:<22ý: 2:} >ͯ :i:2:d*M:[ ͦ>ͦ!q:_  !p+q.*   !q*&!p+q*2:<2!ژ!6 >!]Ҥ; !6:Q::H: !6*M : !6!q:a/>z! *M8):[ͱ!N5!6ñ:5!6#6>!ڰ!6:<2O>/:!O!T *M͡H~K: !36'n::0:f9OY#9.3'ͳ.:020' 'ͳ'7 6'20O> ڒ:0:AO>Ҥ::A }}Hͬ!wͻO`idͻV[2O>2:!X!6:!& !sc*&P :w:·>!ұͯ :22:_!6=!6>'!E!4!p+q*0 !' !'6!36' :1/!aE*#">z?C9IͲÁ.!6> !ڇ*&' ~2 ʀ: y.*M¡!6[–ͱ!N5:2:2!4=:[¼ͱ4:!6:.2O8: :* ͇g!j>A+!s!"@͓1!"<**"͓n "Dn"":!Q2҂:=O!L NE!4 E E:/.*&L 6$L9k9.Xͯ *KM^020r+s+p+q*~$7*>*>H&>*#"*#"> 2:R͎:!6!6=2:ʙ!6:“H!4Q>!қ:=2á:2:Ҭ\>!ҿ:=2K:2K!:!:K\: \!p+q͈*:[ ͱ!N5!6:%:<2*6 * 6å!q!6> !d*&I :]>!4A>:<2O* :w:?†:X!Wғä:ڤ*MEÓ:ұ@@:O2Mc;!6#6>!)*&P ~"::H:H :020:121'ͳ':²ͯ !G6!"!"7 *M^n/ :a/:H!6:ͯ !&69Ž>!6-e!6ͻ2=2ʺ-é:>>"ͻ2:!!5ͻ2ͬ!\DM!  ::=H-\:N2O_og_{ozg^#V))) _{ozg^#V) d^#V|g}o n_{o!6!q!6?!:ҠgÐ!q*&*~!6:22: :]Hں:A2O>: 2ͯ :H:H"!6!4:_jYO jM*"S*" 3@bl*M1͓!""2*">!b!ͯ >!`0ͯ !q:E:24J!46*}a!44EJ *KM^'́:‚-:>>!p+q:,!6*DM9:<!6:z 2W!6D*&L :w:<2Ov*:>=zgO{ozgi`N#Fogo&og H ©=¨÷:S:QHI:N<22: H@"2Í202O> c!6Í202O> ڍ*&O*7 *M^͆ \͔!":͎H*#"ͧÝ/ :>͛9ͯ .*#":_!  and 5 1/4 inch disks. * * DJ 2D/B floppy disk controller with 8 inch disks. * * * * Written by Les Kent and Marc Kus cold boot jump is now a pointer to the * * HDDMA command channel. This pointer was formerly at 40h to 42h. * * * *ength checks for 64K systems * * 9 9 82 Marc SETHIGH was botching 2 sided DPB pointers * * 8 31 82 Marc Changed TRACKS inwarm boot code in the disk drivers * * has been removed. Also, system dependant code has been modified. * * (system dependant82 Marc Deleted the Centronics drivers * * 9 27 82 Marc Changed login message to look like a label * * 9 27 82 Marc Chapper 3/4/82 * * * * Date Programmer Description * * * * 12 30 82 Marc Fixed bad map error retu This IBIOS can be configured to run with the following devices. * * The disks may be configured to run with any or all of the HD driver to HDTRAK * * 8 27 82 Marc Added code/system length checker * * 8 27 82 Marc mwreset save/restores the track  code is code that uses memory locations below * * the IBIOS or code that directly affects the placement of various * * code mnged the login messages to say M5, M10, ... * * 9 27 82 Marc Redefined the dparam table structure * * 9 22 82 Marc Added ;EE rev 0.2 7/16/83 ************************************************************************* * * * Morrow Designs IBrn in GETBAD * **11 10 82 Marc Public release of revision E.31 * * 11 9 82 Marc Reduced bad map size to 1 for non MW sys disk * * systems. The logical order of the disks can be set to any order. * * * * Disk systems: * * HDC3 10number * * 8 26 82 Marc mwreset now sets *step and *dir for CMI * * 8 20 82 Marc Added 'equ'ed handshaking to the serialodules in memory) * * * * Note: One important execption. The DJDMA drivers use addresses * * 50h to 5Bh for coa serial console for the Switchboard * * 9 22 82 Marc Added initialization code for serial group 2 * * 9 22 82 Marc Added IOS for CP/M Version 2.2. * * Copyright (c) 1982, Morrow Designs * * * * This CBIOS has been reconfigured so ttems * * 10 18 82 Marc Fixed SETHIGH for 2 sided DJDMA 8 inch disks * **10 1 82 Marc Public release of revision E.3 * * , 20 and 26 megabyte hard disks. * * HDDMA 5, 10, 16, megabyte hard disk systems. * * DJDMA floppy disk controller with 8 LST: * * 8 19 82 Marc Removed clock switching code from HDCA driver * * 8 18 82 Marc Added handshake configuration code mmand channel information. This area is * * 'reserved' (and not used) by CP/M. * * * * Another note: The IBIOS'sector size byte to the hdca DPB's * * 9 22 82 Marc Added sector size parameter to DPBGEN * * 9 9 82 Marc Fixed system lhat it can run in the * * INSTALL environment. Generally this means that all the console * * drivers, list drivers, and the  9 29 82 Marc 40H now points to the HDDMA command channel * * 9 28 82 Marc MW's now have 1024 directory entries * * 9 28  * * 8 18 82 Marc Added handshake configuration bytes * * 8 18 82 Marc Removed 'equ'ed handshaking from LST: * * 8 12 8ed illegal MAC labels * * 5 11 82 Marc Fixed North Star drive configurations * * 4 30 82 Marc Fixed Quantum Q2040 trackulti density problems * * 6 29 82 Marc Added Olivetti HD561/1 HD561/2 drives * * 6 28 82 Marc Added a MW error reporteric release of revision E.2 * * 2 -- 82 Marc Pre-release testing and debugging * * 2 1 82 Les + Marc Initial coding of r 8 6 82 Marc Fixed the 8 inch dpb256ss DPB's EXM * * 8 6 82 Marc Increased the HD capacities slightly * * 8 6 82 Maroved serial LST: device to port 2 * * 4 1 82 Marc Added common group select routines * * 4 1 82 Marc Fixed Diablo HyTy2 Marc Added configuration entries for a0 & d0 * * 8 11 82 Marc Added the autostart command structure * * 8 11 82 Marc s to 512 * * 4 29 82 Marc Fixed ST412 step constant to 0 * * 4 26 82 Marc Added unallocated writing * * 4 22 82 Mar * * 6 18 82 Marc Added nonstandard system mode flag * * 6 17 82 Marc Added a buffer error flag * * 6 17 82 Marc Aevision E * * * ************************************************************************* title 'IBIOS Revision c Deleted all non-supported MW drives * * 8 6 82 Marc Deleted call to flush in conout * * 8 6 82 Marc Moved printer pe II initialization * * 4 1 82 Marc Fixed LISTST for PROM driver * * 3 16 82 Marc Added Tandon TM602 and TM603 drivesRedefined the configuration table * * 8 11 82 Marc Added DJDMA drive parameter table * * 8 9 82 Marc Added clock switchc Fixed HD partition overlap * * 4 20 82 Marc Started testing and debugging of E.3 * * 4 19 82 Marc Added 1 sector to dded save/restore of 50-52 to MW driver * * 6 17 82 Marc Fixed Centronics drivers * * 6 7 82 Marc Fixed allocation map E for CP/M Version 2.2 - March 4, 1982' revnum equ 53 ;IBIOS revision number 5.x = E.x cpmrev equ 22 ;CP/M revision numberback to port 3 * * 7 28 82 Marc Moved conin flush call to conout * * 7 27 82 Marc Fixed double sided head settle time  * * 3 16 82 Marc Use 'part number' equates for MW drives * * 3 15 82 Marc Dropped hdrev and mwrev equates * * 3 15 ing to HDCA code * * 8 9 82 Marc Added seek complete clearing in HDCA * * 8 6 82 Marc Added buffer disable on home *HD warm boot loader * * 4 19 82 Marc Added mod. number to IBIOS rev. number * * 4 19 82 Marc Clean up login message 'if'sizes * * 6 7 82 Marc Fixed MW partitioning * * 6 7 82 Marc Fixed HD partitioning (again) * * 5 13 82 Marc Fix 2.2 ************************************************************************* * * * The following equates set up t* * 7 14 82 Marc Optimized MWissue * * 7 14 82 Marc Clean up login message for HD a bit * * 6 30 82 Marc Fixed MF m82 Marc Seagate ST506 head settle is 0 ms. * * 3 15 82 Marc Added MiniScribe 1006 and 1012 drives * * *3 1 82 Marc Publ * 8 6 82 Marc Fixed 8250 UART initialization sequence * * 8 6 82 Marc Strip parity on conout to clear up glitches * *s * * 4 15 82 Marc Fixed MCR Initialization for LST: * * 4 15 82 Marc Added Seagate ST412 drive * * 4 6 82 Marc M he disk systems to be included * * along with the types of drives and the logical order of the * * drives. * *  in length. * * * * All hard disk drives shipped from Morrow Designs are partitioned * * using the standard partitr drives using two different * * formulas. * * * * One is the so called 'standard partitioning' where we try t endif hdc3 equ m26 or m20 or m10 ;HDC3 controller fujitsu equ m20 or m10f hdspt equ 32*m26+21*m20+21*m10 ;Sectors perer equ 0 mforder equ 0 ;HDC3 controller disk drives. Set only one m10f equ 0 ;Fujitsu M2301B m20 equ 0 ;Fujitsu M2302B * ************************************************************************* if maxmw ne 0 badsiz equ 32 ;Number of b * ************************************************************************* numprd equ 5 ;Number of disks products suppoion formula. If the user wishes to * * implement even partitioning then he/she must set HDPART or MWPART * * to the number oo * * create as many 8 megabyte partitions as possible plus a small * * partition to take up the slack on the end of the dri track hdma set st506 or st412 or cm5619 ;HD DMA controller mwspt equ 9 ;Sectors per track maxlog equ (maxhd*hdlog)+(m m26 equ 0 ;Shugart SA4000 m10m equ 0 ;Memorex ;HDDMA controller disk drives. Set only one st506 equ 0 ;Seagate ST-admap entries else badsiz equ 1 ;No badmap if no MW drives endif m10 equ m10f or m10m if hdpart ne 0 ;Use non started maxhd equ 0 ;Set to number of HDC3 hard disk drives maxmw equ 1 ;Set to number of HDDMA hard disks maxfd equ 0 ;Setf partitions desired. * * * ************************************************************************* hdpart eqve. * * * * Another way the drives are partitioned is the so called 'even * * partition' formula. This means that axmw*mwlog)+maxfd+maxdm+maxmf if maxlog gt 16 ;Test for too many drives 'Fatal error, more that 16 drives specified.' en506 st412 equ 0 ;Seagate ST-412 cm5619 equ 1 ;CMI CM-5619 ***************************************************************ndard partitions hdlog equ hdpart else hdlog equ m10*2+m20*3+m26*3 ;Logical disks per drive for HDC3 endif if mwpart n to number of 2D/B floppies maxdm equ 0 ;Set to number of DJ DMA floppies 8 inch maxmf equ 0 ;Set to number of DJ DMA floppiu 0 ;Set to number of non standard partitions mwpart equ 0 ;Set to number of non standard partitions *********************the drive is split into * * equale sized partitions with the only restriction being that no * * partition be over 8 megabytesd endif cdisk equ 4 ;Address of last logged disk bdos equ 5 ;BDOS entry point buff equ 80h ;Default buffer address ********** * * * Since most hard disk drives hold more than 8 megabytes we * * partition the drive. We partition oue 0 ;Use non standard partitions mwlog equ mwpart else mwlog set st506+st412*2++cm5619*2 ;Logical disks per drive for HDDMAes 5 1/4 inch hdorder equ 0 ;Set the order of logical drives ELSE 0 if mworder equ 1 ; not included. fdorder equ 0 dmord**************************************************** * * * The following equates are internal to the IBIOS. * *  cpmout equ 2 ;BDOS's console output routine ************************************************************************* * ************* * * * The following marco is used in generating the logical order of the * * CP/M drives. * * ***************** dpbgen macro nam,log,dspt,dbsh,dblm,dexm,ddsm,ddrm,dal0,dal1,dcks,doff,ssiz dpb&nam&log equ $ dw dspt ump table below must remain in the same order, the routines * * may be changed, but the function executed must be the same. * L'-64 ;Form Feed acr equ 'M'-64 ;Carriage return xon equ 'Q'-64 ;Xon character xoff equ 'S'-64 ;Xoff character aesc equ *********************************************** d$wboot equ 0 ;Warm boot d$stran equ 1 ;Sector translation d$sel1 equ 2 ;Dr * * The following are internal IBIOS equates. Most are misc. constants. * * * ********************************** * ************************************************************************* order macro num if num eq hdorder dw db dbsh db dblm db dexm dw ddsm dw ddrm db dal0 db dal1 dw dcks dw doff db ssiz endm dphgen macro nam,log * * ************************************************************************* bios equ $ ;Starting location jm1bh ;Escape character ars equ 1eh ;RS character aus equ 1fh ;US character asp equ ' ' ;Space adel equ 7fh ;Delete **ive select, Return DPH d$sel2 equ 3 ;Drive select d$home equ 4 ;Home drive d$strk equ 5 ;Set track d$ssec equ 6 ;Set sector *************************************** retries equ 10 ;Max retries on disk i/o before error clear equ 'Z'-64 ;Clear screehddst endif if num eq mworder dw mwdst endif if num eq fdorder dw fddst endif if num eq dmorder dw dmdst,dpb1,dpb2 dph&nam&log equ $ dw 0 dw 0,0,0 dw dirbuf dw &dpb1&dpb2 dw csv&nam&log dw alv&nam&log endm alloc map $ ;Cold boot entry point owboot: jmp wboot ;Warm boot entry point jmp $ ;Console status routine jmp $ ;Console input *********************************************************************** * * * The following are the macros used in gen d$sdma equ 7 ;Set DMA address d$read equ 8 ;Read a physical sector d$write equ 9 ;Write a physical sector d$bad equ 10 ;Retun on an ADM 3 anul equ 0 ;Null aetx equ 'C'-64 ;ETX character aack equ 'F'-64 ;ACK character abel equ 'G'-64 ;Bell ab endif if num eq mforder dw mfdst endif endm ********************************************************************cro nam,log,al,cs csv&nam&log: ds cs alv&nam&log: ds al endm ************************************************************ ocout: jmp $ ;Console output jmp $ ;List device output jmp $ ;Punch device output jmp $ ;Reader device input ohome: erating the DPH, DPB and * * allocation tables. * * * ********************************************************rn pointer to bad sector info ************************************************************************* * * * The js equ 'H'-64 ;Back Space aht equ 'I'-64 ;Horizontal tab alf equ 'J'-64 ;Line feed avt equ 'K'-64 ;Vertical tab aff equ '***** * * * The folloing are offset numbers of Device Specification Tables. * * * **************************  jmp home ;Home drive osetdrv:jmp setdrv ;Select disk osettrk:jmp settrk ;Set track osetsec:jmp setsec ;Set sector osetdmfixed length fields. The fields * * are defined as follows: * * * * tracks This byte contains the number of tra * * The following table are drive parameters for drives connected to * * the DJDMA floppy disk controller. There is one entrg * * after the heads have been stepped. Example, * * Shugart's SA 850 head settle time is 15 now ************************************************************************* * * * The following is the table of phe step constant would be the * * drive manufactors recomended stepping delay times * * 34.1. Exaa:jmp setdma ;Set DMA address oread: jmp read ;Read the disk owrite: jmp write ;Write the disk jmp $ ;List device statuscks on the * * drive. Most 8 inch drives have 77 tracks and * * most 5 1/4 inch drives have 35 y for each of * * the the eight drive that the controller can address. The first * * four entries are for the 8 inch drives a* * milliseconds. The settle constant would be 15 * * * 34.1 or 512. * * * * An asointers to the Device * * Specification Tables. The order of this table defines the * * logical order of the CP/M drives. mple. Shugart SA 850's step at 3 * * milliseond intervals. The step constant would be * * 3 * 4 osect: jmp sectran ;Sector translation jmp $ ;Hookup for SINGLE.COM program nop ;End of table *******************or 40 tracks. * * * * config This a a flag byte that indicates as to whether * * or not this drive hand the last four are for * * the 5 1/4 inch drives. Users with fast stepping 8 inch drives * * (SA850/1) or slow 5 1/4 inch dsembler macro (DCONF) has been provided to assist in * * generating the DPARAM table. This macros parameters are the * * nu * * * ************************************************************************* dsttab: equ $ dn set 1 rep3.1 or 102. * * * * rfu The next two words are reserved for future use. * * They must be zero. * * ****************************************************** * * * Drive configuration table. * * * *********s been configured. Set to * * 0 to force reconfiguration. * * * * step This word contains the steprives (SA400) should adjust this * * table for optimal device performace. * * * * Each table entry contains four mber of tracks, the step rate in milliseconds, and the head * * settle time in milliseconds. For example: * * * t numprd order %dn dn set dn+1 endm ************************************************************************* *  * * settle This word is similar to the previously defined * * step word. This specifies the head settle timin**************************************************************** drconf: db 0 ;Revision 0 structure db 32 ;32 bytes long ping rate constant. * * The DJDMA's delay routines tick 34.1 times per * * millisecond. Thus t  * ;Shugart SA 850 * * dconf 77, 3, 15 ;77 tracks, 3 ms step, 15 ms settle * * * * ;Shugart SA 400 * * dc0, 5, 15 ;Drive 1 dconf 40, 5, 15 ;Drive 2 dconf 40, 5, 15 ;Drive 3 endif ***************************************** ************************************************************************* dconf 77, 8, 8 ;Drive 0 dconf 77, 8, 8 ;Dri*************************************** * * * Install packages drive select routine. This routine checks the * * ext tracks db 0 ;Reset the calibrated flag dw step*341/10 ;Step time dw 0 ;Reserved for future use, must be zero dw 0 age warm boot. This routine inspects the command * * buffer for a drive specification. If present then the local * * driveonf 35, 40, 10 ;35 tracks, 40 ms step, 10 ms settle * * * * Note: Caution should be used when defining the drive param********************************* * * * DPH save area. Each entry is 4 bytes long: * * 0 - LSB of DPH address ve 1 dconf 77, 8, 8 ;Drive 2 dconf 77, 8, 8 ;Drive 3 ******************************************************************ernal drive name to determine if the drive belongs to the host * * system or to the install drivers (local drives). The flag I ;Reserved for future use, must be zero dw settle*341/10 ;Head settle time endm dmarap: db 0, 10*8 ;Revision 0, lengts are 'relocated' to the user specified loaction. A 'map' * * of the drive configuration is printed. * * * ******eters. * * Incorrect definations may damage the floppy disk drive. Morrow * * Designs takes no responsibility for damage tha * * 1 - MSB of DPH address * * 2 - Sector size code (1 = 128, 2 = 256, 3 = 512... * * 3 - Bad map has been initilized******* * * * Define 5 1/4 inch drive parameters * * Use Tandon parameters: 40 tracks, 5 ms step, 15 ms settle *NSERV * * (in service) is set accordingly. If the drive belongs to the * * host system then the drive name is adjusted (so th 80 bytes dparam: equ $ ;Drive parameter table ******************************************************************************************************************************************* wboot: mvi a,0ffh ;One time code flag inr a jnz owbt occures through * * the misuse of this macro. * * * ********************************************************** (0 = Uninitilized) * * * ************************************************************************* dphtab: rept m * * ************************************************************************* dconf 40, 5, 15 ;Drive 0 dconf 4hat the host * * system does not know that we are here, shhh) and the host drive * * select routine is called. * * * * * * Define 8 inch drive parameters * * Use SA800 parameters: 77 tracks, 8 ms step, 8 ms settle * * oot sta wboot+1 ;Clear one time flag jmp insetu ;Do install package setup routines ************************************************* if (maxdm ne 0) or (maxmf ne 0) ;DJDMA present? dconf macro tracks, step, settle db tracks ;Number ofaxlog dw 0, 0 endm ************************************************************************* * * * Install pack   * ************************************************************************* drvsel: mov a,c ;Get the external drive naision byte and a length byte. * * The revision byte is the current revision number for that * * particular structure and th* * * * Install package variables. * * * **************************************************************cally invoke a command on cold or warm boot * * * * 5) This will be a null (0) pointer. It marks the end of the * ********* * * * Determine if the installed drivers are currently giving * * service to CP/M. If so then return else po * * * * 1) This points to the drive configuration table. * * * * 2) This points to the I/O configuratme lxi h,dlocal ;Test against the first local drive sub m jc drvsl1 ;Skip if the host drive is below us cpi maxlog e length byte is the length of that * * structure. This length does not include the revision byte nor * * the length byte its*********** dlocal: db 16-maxlog ;First external drive used locally inserv: db 0 ;Local drive in service flag ******** table. * * * ************************************************************************* if $ gt bios+p off return * * address and jump to (hl). * * * *****************************************************************ion bytes for the serial * * drivers. Eg, the console, printer, reader, and punch * * devices. * * ;See if this drive is within our range jnc drvsl0 mov c,a ;Load the local drive name mvi a,0ffh ;Set the in service flelf. * * * * Revision Description * * E.0 1 and 2 defined * * E.3 This table is moved to a page bound***************************************************************** * * * At the first page boundry following the IBIOS 256 ;Test for code overlap 'Fatal error, pointer table placement.' else ds bios+256-$ ;Pad spaces till the next page end serv: lda inserv ;Test the in service flag ora a rnz ;Return if we are servicing this one xthl ;Clear out the  * * 3) This points to the drive parameter table for DJDMA floppy * * disk drives. If no DJDMA is present then this poag jmp drvsl2 drvsl0: mov a,c ;Adjust the host drives above us sui maxlog mov c,a drvsl1: xra a ;Clear the in servry * * E.3 0, 3 and 4 defined * * * * The pointers defined so far are as follows: * * * * 0) High bwe have a series of * * pointers that point to various internal tables. At the start of * * each of these tables we have a revif db high ($-1) ;IBIOS page number db revnum ;IBIOS revision number dw drconf ;Drive configuration table pointer dwcall to SERV donop: ret ;'jump' to the host call ************************************************************************inter is * * null (0). * * * * 4) This points to the autostart command structures. Used to * * automatiice flag drvsl2: sta inserv ret ;Return to IBIOS's setdrv *********************************************************yte is the page number of the IBIOS. Low byte is * * the IBIOS revision number. Used to determine pointer * * structure.   0 ;I/O configuration pointer (DELETED BY INSTALL) if (maxdm ne 0) or (maxmf ne 0) ;DJDMA present? dw dmarap ;Drive parameber in (bc) mov l,c shld cpmtrk jmp osettrk ***************************************************************** *  lda bufwrtn ;Test buffer dirty flag ora a jnz dohome ;Skip buffer disable if buffer dirty xra a ;Invalidate buffer on v a,c ;Save the logical drive number sta cpmdrv cpi maxlog ;Check for a valid drive number jnc zret ;Illegal drive ******************************** * * * Setdma saves the DMA address for the data transfer. * * * ************ve has never been selected it calls * * a low level drive select routine that should perform some * * sort of check if the devter table pointer else dw 0 endif dw 0 ;Auto command structure pointer (DELETED) dw 0 ;End of table marker ****** * * Sectran translates a logical sector number into a physical * * sector number. * * * *********************home call sta bufsec dohome: lxi b,0 ;Track to seek to ***************************************************************** mov a,e ;Check if bit 0 of (e) = 1 ani 1 jnz setd3 ;Drive has allready been accessed mov h,c ;Move logical drive into***************************************************** setdma: mov h,b ;Enter with DMA address in (bc) mov l,c shld cpmdmice is working. If not working then * * it should report an error. If the logical drive has been * * selected before then se*********************************************************** * * * Setsec just saves the desired sector to seek to until******************************************** sectran:lxi h,osect call serv lda cpmdrv ;Get the Drive Number mov h,a ; * * * Settrk saves the track # to seek to. Nothing is done at this * * point, everything is deffered until a read or w (h) mvi l,d$sel1 call jumper ;Call low level drive select mov a,h ;Check if the low level drive select returned ora la ;CP/M dma address jmp osetdma ***************************************************************** * * * Home is ttdrv just returns the DPH without * * checking the drive. * * * ************************************************* an * * actual read or write is attempted. * * * ***************************************************************** Drive in (h) mvi l,d$stran jmp jumper ;See device level sector translation routines ************************************rite. * * * ***************************************************************** settrk: mov h,b ;Enter with track num ; zero to indicate an error jz zret ;Yes, an error so report to CP/M push h ;Save DPH address call gdph ;Get entry ranslated into a seek to track zero. * * * ***************************************************************** home:**************** setdrv: call drvsel ;Do INSTALL checking lxi h,osetdrv ;Vector to the host drive select call serv mo setsec: mov h,b ;Enter with sector number in (bc) mov l,c shld cpmsec jmp osetsec ************************************************************** * * * Setdrv selects the next drive to be used in read/write * * operations. If the dri  if DPH save table pop d ;DPH -> (de) mov m,e ;Put address of DPH in table inx h mov m,d inx h mov m,c ;Put sector push d lda cpmdrv ;Pick up current drive mov h,a ;Call drive routine to return a pointer to mvi l,d$bad ;the track andGet last selected drive mov c,a lda cdisk ;Pick up user/drive ani 0f0h ;Save user number ora c ;Put together with oldobad: lxi h,0 ;Used by device drives to indicate no bad ret ; sector map badptr: dw badmap ;Pointer to next available b ;Save DPH address mov h,c ;Drive in (h) mvi l,d$sel2 ;Select drive call jumper call gdph ;Quick select pop d movart at beginning of buffer badl: ldax d ;Pick up an entry from the buffer ora a jz bade ;All done mov a,m ;Pick up ent size in table inx h mov a,m ;Check if bad map has ever been read for this ora a ; drive cz getbad ;Never been read s sector of the bad map call jumper mov a,h ;If routine returns 0 then the device has ora l ; no bad sector map jz ba drive sta cdisk ret ***************************************************************** * * * Getbad - Check if aad map entry ***************************************************************** * * * Write routine moves data from m e,m ;DPH -> (de) inx h mov d,m inx h mov c,m ;Sector size -> (c) xchg ;DPH -> (hl) jmp setd0 gdph: lda cpmdrry from bad map table inr a jz overflo ;Bad map overflow lda cpmdrv ;Put drive in table mov m,a inx h lxi b,8 cao read in bad map xchg ;DPH -> (hl) setd0: mov a,c ;Move sector size code into (a) sta secsiz ;Save sector size xradret mov e,m ;Pick up track number of bad sector map -> (de) inx h mov d,m inx h xchg shld cpmtrk xchg mov a, device has a bad map. If the device has * * a bad sector map then append bad entries to end of badmap * * table. * * emory into the buffer. If the * * desired CP/M sector is not contained in the disk buffer, the * * buffer is first flushed to v ;Return pointer to DPH save area rlc ;Each entry is 4 bytes long rlc mov e,a mvi d,0 lxi h,dphtab ;DPH save area ll movbyt ;Move the rest of information into the table jmp badl bade: shld badptr ;Restore new bad map pointer badret: p a setd1: dcr c ;Create number of (128 bytes/physical sector)-1 jz setd2 rlc ori 1 jmp setd1 setd2: sta secpsec ;Savm ;Pick up sector number of of bad sector map inx h mov h,m mov l,a shld truesec call fill ;Read in bad sector map i * ***************************************************************** getbad: mvi m,1 ;Set drive initilized push b the disk if it has ever been * * written into, then a read is performed into the buffer to get * * the desired sector. Once thtable dad d ;Add offset ret ;(hl) = DPH save area for current drive zret: lxi h,0 ;Seldrv error exit lda lastdrv ;op d pop b ret overflo:lxi h,omes call message jmp badret omes: db 0dh, 0ah, 'BAD MAP OVERFLOW!', 0dh, 0ah, 0 ne for deblocking lda cpmdrv ;Save current drive as old drive sta lastdrv ; in case of select errors ret setd3: push dnto the buffer jc badret ;Ingore the bad map if it can't be read lhld badptr ;Pick up bad map pointer lxi d,buffer ;St e correct sector is in memory, the * * buffer written indicator is set, so the buffer will be * * flushed, then the data is tr/M sector # mov a,h ani 80h ;Save only the side bit mov c,a ;Remember the side mov a,h ani 7fh ;Forget the side bit physical sector on the disk that * * contains the desired CP/M sector, then checks if it is the * * sector currently in the brect physical sector rc ;No good, return with error indication **********************************************************the buffer does not contain the desired sector, the buffer is * * flushed to the disk if it has ever been written into, then * Test if done with compare jz move ;Yes, match. Go move the data ldax d ;Get a byte to compare cmp m ;Test for match iansferred into the buffer. * * * ***************************************************************** write: lxi h,owri mov h,a dcx h ;Temporary adjustment divloop:dcr b ;Update repeat count jz divdone ora a mov a,h rar mov h,a uffer. If no match is made, the * * buffer is flushed if necessary and the correct sector read * * from the disk. * * ******* * * * Move has been modified to cause either a transfer into or out * * the buffer. * * * ***** * filled with the sector from the disk that contains the * * desired CP/M sector. * * * ************************nx h ;Bump pointers to next data item inx d jz dtslop ;Match, continue testing ****************************************te call serv mov a,c ;Save write command type sta writtyp mvi a,1 ;Set write command jmp rwent ******************mov a,l rar ;Divide the CP/M sector # by the size ; of the physical sectors mov l,a jmp divloop ; divdone:inx h  * ***************************************************************** redwrt: mvi b,0 ;The 0 is modified to contain the ************************************************************ move: lda cpmsec ;Get the CP/M sector to transfer dcr a ;Adj***************************************** read: lxi h,oread call serv xra a ;Set the command type to read rwent: sta rd************************* * * * Drive, track, and sector don't match, flush the buffer if * * necessary and then refil*********************************************** * * * Read routine to buffer data from the disk. If the sector * * req mov a,h ora c ;Restore the side bit mov h,a shld truesec ;Save the physical sector number lxi h,cpmdrv ;Pointer to delog2 secsiz equ $-1 ; of the physical sector size/128 ; on the currently selected disk lhld cpmsec ;Get the desired CPust to proper sector in buffer ani 0 ;Strip off high ordered bits secpsec equ $-1 ;The 0 is modified to represent the # of wr ;Save command type ***************************************************************** * * * Redwrt calculates thel. * * * ***************************************************************** call fill ;Fill the buffer with coruested from CP/M is in the buffer, then the data is simply * * transferred from the buffer to the desired dma address. If * * sired drive,track, and sector lxi d,bufdrv ;Pointer to buffer drive,track, and sector mvi b,6 ;Count loop dtslop: dcr b ;  ; CP/M sectors per physical sectors mov l,a ;Put into HL mvi h,0 dad h ;Form offset into buffer dad h dad h d * * * ***************************************************************** prep: call alt ;Check for alternate sect********** flush: mvi a,0 ;The 0 is modified to reflect if ; the buffer has been written into bufwrtn equ $-1 ora a in ***************************************************************** * * * Fill fills the buffer with a new sector fto: xchg ; call mov128 ;Move the data, HL = destination ; DE = source mvi a,1 sta bufwrtn ;Set buffer written int,buffer ;Set the DMA address mvi l,d$sdma call jumpbuf rwop: mvi l,0 ;Get operation address call jumpbuf pop b ;Rad h dad h dad h dad h lxi d,buffer ;Beginning address of buffer dad d ;Form beginning address of sectgr to transfer ors di ;Reset interrupts xra a ;Reset buffer written flag sta bufwrtn mvi b,retries ;Maximum number of retries to a ;Test if written into rz ;Not written, all done mvi a,d$write sta rwop+1 call prep ;Do the physical write sta errorom the disk. * * * ***************************************************************** fill: call flush ;Flush buffeo flag mvi a,0 ;Check for directory write writtyp equ $-1 dcr a ;Test for a directory write mvi a,0 rnz ;No error eestore the retry counter mvi a,0 ;No error exit status rnc ;Return no error dcr b ;Update the retry counter stc ;A xchg ;DE = address in buffer lxi h,0 ;Get DMA address, the 0 is modified t/ ; contain the DMA address cpmdma equ $-ttempt retrylp:push b ;Save the retry count mvi l,d$sel2 ;Select drive call jumpbuf lhld alttrk ;Track number -> (hr ;Set up the error flag ret ***************************************************************** * * * Prep preparer first rc ;Check for error lxi d,cpmdrv ;Update the drive, track, and sector lxi h,bufdrv lxi b,5 ;Number of bytes txit ***************************************************************** * * * Flush writes the contents of the buffer ssume retry count expired mvi a,0ffh ;Error return rz ;Return sad news mov a,b cpi retries/2 jnz retrylp ;Try agai2 mvi a,0 ;The zero gets modified to contain ; a zero if a read, or a 1 if write rdwr equ $-1 ana a ;Test which kindl) mov a,h ;Test for track zero ora l push h ;Save track number mvi l,d$home cz jumpbuf pop b ;Restore track s to read/write the disk. Retries are attempted. * * Upon entry, H&L must contain the read or write operation * * address. o move call movbyt ;Copy the data lda rdwr ;Test read write flag ora a jz fread ;Skip write type check if reading out to the disk if * * it has ever been written into. * * * *******************************************************n push b ;Save retry count mvi l,d$home ;Home drive after (retries/2) errors call jumpbuf pop b jmp retrylp ;Try aga of operation jnz into ;Transfer data into the buffer outof: call mov128 lda error ;Get the buffer error flag ret in# mvi l,d$strk call jumpbuf lhld altsec ;Sector -> (hl) mov b,h mov c,l mvi l,d$ssec call jumpbuf lxi b  lda writtyp ;0 = alloc, 1 = dir, 2 = unalloc sui 2 ;Test for an unallocated write rz fwritin:lda secsiz ;Check for **************************** * * * Check for alternate sectors in bad sector table. If an * * alternate sector is fou DST jnc jumpl ;Keep scanning table till correct driver found inx h ;Bump (hl) to point to start of dispatch table popf alternate sector lda bufsec ;Pick up LSB of buffer sector cmp m jnz altmis inx h ;Point to MSB of alternate sector s * * a call to jumper with the drive number from bufdrv. * * * *****************************************************lhld buftrk ;No alternate sector so use selected sector shld alttrk lhld bufsec shld altsec ret alt2: push h ;Save 128 byte sectors dcr a rz ;No deblocking needed fread: mvi a,d$read sta rwop+1 call prep ;Read the physical sectornd replace alttrk and altsec with * * new sector number else pass along unaltered. * * * *************************** d ;Real (hl) -> (de) mov a,e ;Move offset number into (a) rlc ;Each entry is 2 bytes mov e,a ;Make an offset mvi d lda bufsec+1 ;Pick up MSB of buffer sector cmp m jnz altmis ;Found an alternate sector inx h ;Point to real info on the************ jumpbuf:lda bufdrv ;Dispatch with bufdrv for drive mov h,a jumper: push d push b push h mov a,h ;Locurrent bad map entry address mov a,c ;Move drive into (a) cmp m ;Check if drive in table matches jnz altmis ;Does not  the buffer sta error ;Set the error status ret ***************************************************************** * ************************************** alt: lxi h,badmap ;Address of bad map -> (hl) lda bufdrv ;Pick up drive number curr,0 dad d ;(hl) = **Routine mov a,m ;Pick up address of handler for selected inx h ; function mov h,m mov l,a ;(hl) alternate sector lxi d,alttrk xchg ;MOVLOP (de) = source, (hl) = dest push b lxi b,4 call movbyt ;Move alternate sgical drive into (a) lxi d,dsttab ;Drive specification pointer table jumpl: mov c,a ;Save logical in (c) ldax d mov l,a match skip this entry inx h ;Point to LSB of alternate track lda buftrk ;Pick up LSB of buffer track cmp m jnz altmis  * * Jumpbuf, jumper are used to dispatch to a low level device * * subroutine. Jumper is called with the drive in (h) andently working on mov c,a ;Move drive into (c) for speed in search all: xchg lhld badptr ;Get bad map pointer xchg ; - = *routine mov a,c ;Logical in (a) pop b ;Restore saved registers pop d pchl *************************************ector info in correct place pop b pop h ret altmis: pop h ;Current alternate did not match lxi d,9 ;Bump pointer by inx d ldax d mov h,a ;Get a DST pointer in (hl) inx d mov a,c ;Logical in (a) sub m ;Subtract from first entry in inx h ;Point to MSB alternate track lda buftrk+1 ;Pick up MSB of buffer track cmp m jnz altmis inx h ;Point to LSB o the * * routine number (see description above) in (l). It passes * * along the (bc) and (de) registers unaltered. Jumpbuf i> (de) mov a,d ;Check if at end of bad map table cmp h jnz alt2 ;Still more mov a,e cmp l jnz alt2 ;Still more   the length of an entry dad d jmp all ;Loop for more ***************************************************************** op h ;Restore the pointer jmp message ;Continue until null reached ******************************************************l) = pointer to DPH ret ***************************************************************** * * * Utility routine to02h ;Retry flag ; Command port (51) idbuff equ 0 ;Initialize data buffer pointer rsect equ 1 ;Read sector wsect eq;Source in (hl), Destination in (de) dw 0b0edh ;ldir xchg ret ********************************************************dorg+3 ;Data port ; Status port (50) tkzero equ 01h ;Track zero opdone equ 02h ;Operation done complt equ 04h ;S* * * Mover moves 128 bytes of data. Source pointer in DE, Dest * * pointer in HL. * * * *************************** * * * The following code is for the Diskus Hard disk * * * ************************************** output the message pointed at by (hl) * * terminated with a null. * * * *****************************************u 5 ;Write sector isbuff equ 8 ;Initialize header buffer pointer ; Function port (52) pstep equ 04h ;Step bit nste********* * * * Return DPH pointer. Enter with (de) with DPH base address * * and (a) with logical drive number. Reteek complete tmout equ 08h ;Time out wfault equ 10h ;Write fault drvrdy equ 20h ;Drive ready index equ 40h ;Delta in************************************************* mov128: lxi b,128 ;Length of transfer movbyt: xra a ;Check if host proce*************************** if hdc3 ne 0 ;Want HDC3 or 4 controller included ? hdorg equ 50h ;Hard Disk Controller ori************************ message:mov a,m ;Get a character of the message inx h ;Bump text pointer ora a ;Test for end p equ 0ffh-pstep ;Step bit mask null equ 0fch ;Null command ; Misc constants hdrlen equ 4 ;Sector header length securns with DPH address * * in (hl). * * * ***************************************************************** redex ; Control port (50) hdfren equ 01h ;Enable external drivers hdrun equ 02h ;Enable controllers state machine hdclssor is a Z80 adi 3 jpo z80mov ;Yes, Its a Z80 so use block move m8080: ldax d ;Get a byte of source mov m,a ;Move igin hdstat equ hdorg ;Disk Status hdcntl equ hdorg ;Disk Control hdreslt equ hdorg+1 ;Disk Results hdcmnd equ hdorg+ rz ;Return if done push h ;Save pointer to text mov c,a ;Output character in C call ocout ;Output the character plen equ 512 ;Sector data length ***************************************************************** * * * Device Spetdph mov l,a ;Move logical drive into (l) mvi h,0 dad h ;Multiply by 16 (size of DPH) dad h dad h dad h dad d ;(hok equ 04h ;Clock source control bit, high = disk hdwprt equ 08h ;Write protect a drive ; Result port (51) retry equ t inx d ;Bump pointers inx h dcx b ;Update counter mov a,b ;Test for end ora c jnz m8080 ret z80mov: xchg 1 ;Disk Commands hdskomp equ hdorg+2 ;Seek complete clear port (on HDC4) hdfunc equ hdorg+2 ;Function port hddata equ h cification Table for HDCA controller driver * * * ***************************************************************** ve 30 ms head settle xra a ;HL/2 + HL (same as HL*1.5) mov a,h rar mov d,a mov a,l rar mov e,a dad d endif rror in hdstat ;Test if ready yet ani drvrdy jnz hdtdel if not fujitsu lxi h,0 ;Time one revolution of the driveet endif hdseek: call hdptr ;Get pointer to current track mov e,m ;Get current track mov m,c ;Update the track kewwing inx h ret hdldrv: sta hdcur ;Save logical disk call divlog ;Divide by logical disks per drive mov a,c srite protect out hdcntl ret hdhome: call hdptr ;Get track pointer mvi m,0 ;Set track to zero in hdstat ;Test st hddst: db maxhd*hdlog ;Number of logical drives dw donop ;No warm boot for INSTALL dw hdtran ;Sector translation dw  shld settle ;Save the count for timeout delay endif call hdhome hdl2: lda hdcur ;Load logical drive lxi d,dphh mvi c,index in hdstat ana c mov b,a ;Save current index level in B hdinxd1:in hdstat ana c cmp b ;Loop untill mov a,e ;Need to seek at all ? sub c rz cmc ;Get carry into direction jc hdtrk2 cma inr a if fujitsu hdtrk2:ta hddisk ;Save new physical drive call hdptr ;Get track pointers mov a,m ;Get current track inr a ;Check if -1 atus ani tkzero ;At track zero ? rz ;Yes if not fujitsu hdstepo:in hdstat ;Test status ani tkzero ;At track hdldrv ;First time select dw hddrv ;General select dw hdhome ;Home current selected drive dw hdseek ;Seek to selecd0 ;Start of hard disk DPH's mvi c,3 ;Hard disk sector size equals 512 bytes jmp retdph dcrc: dcr c ;Conditional decindex level changes jz hdinxd1 hdindx2:inx h in hdstat ;Start counting untill index returns to ana c ; previous state jmp accok else hdtrk2: call accok jmp hddelay endif accok: mov b,a ;Prep for build call build sloop: ani nstep jnz hdl2 ;Nope, allready accessed ori null ;Select drive out hdfunc mvi a,hdfren+hdclok ;Enable drivers out hdcntl zero ? jz hddelay mvi a,1 stc call accok ;Take one step out jmp hdstepo else xra a jmp accok endif ited track dw hdsec ;Select sector dw hddma ;Set DMA address dw hdread ;Read a sector dw hdwrite ;Write a sector rement C routine ret divlog: mvi c,0 divlx: sui hdlog rc inr c jmp divlx hddrv: sta hdcur call divlog ;Get th cmp b jnz hdindx2 if m10 ;Memorex M10's have 40 ms head settle dad h ;HL*2 endif if m26 ;Shugart M26's ha ;Get step pulse low out hdfunc ;Output low step line ori pstep ;Set step line high out hdfunc ;Output high step lin mvi c,239 ;Wait 2 minutes for disk ready lxi h,0 hdtdel: dcx h mov a,h ora l cz dcrc jz zret ;Drive not ready ef not fujitsu hddelay:lhld settle ;Get hddelay deloop: dcx h ;Wait 20ms mov a,h ora l inx h dcx h jnz deloop r dw nobad ;No bad sector map hdtran: mov h,b ;Sector translation is handled via mov l,c ; physical sector header se physical drive # hdd2: mov a,c sta hddisk ;Select the drive ori null out hdfunc mvi a,hdfren+hdrun+hdclok+hdwprt ;W e dcr b ;Update repeat count jnz sloop ;Keep going the required # of tracks jmp wsdone hddma: mov h,b ;Save the D:in hdstat ;Wait for command to finish mov b,a ani opdone jz process mvi a,hdfren+hdrun+hdclok ;Write protect out hdhddata mov m,a inx h in hddata mov m,a inx h in hddata mov m,a inx h dcr b jnz rtloop ret hdwrite:call ical head number hdsect: db 0 ;Current physical sector number hdtrak: db 0ffh ;Track pointer for each drive db 0ffh ,hdspt ret else hdsec: mov a,c call divspt adi hdspt ana a cz getspt sta hdsect mov a,c sta head getspt:,hdfren+hdrun+hdclok ;Write protect out hdcntl mvi a,hdfren+hdrun+hdclok+hdwprt ;Write protect out hdcntl xra a ret MA address mov l,c shld hdadd ret wsdone: in hdstat ;Wait for seek complete to finish ani complt jz wsdone in hcntl in hdstat ani tmout ;Timed out ? stc rnz in hdreslt ani retry ;Any retries ? stc rnz xra a ret hhdprep ;Prepare header rc xra a out hdcmnd lhld hdadd mvi b,seclen/4 wtloop: mov a,m ;Move 4 bytes out hddata ;All drive default to an uncalibrated db 0ffh ; state (ff) db 0ffh settle: dw 0 ;Time delay constant for head settl mvi a,hdspt dcr c ret divspt: mvi c,0 divsx: sui hdspt rc inr c jmp divsx endif hdread: call hdprep rc x hdptr: lhld hddisk ;Get a pointer to the current drives mvi h,0 ; track position xchg lxi h,hdtrak dad d ret dskomp ;Clear sdone bit on an HDCA4 ret if m26 hdsec: mvi a,01fh ;For compatibility with IBIOS revs. ; 2.3 anddprep: in hdstat ani drvrdy stc rnz mvi a,isbuff ;Initialize pointer out hdcmnd call build ori 0ch out hdfunc  inx h mov a,m out hddata inx h mov a,m out hddata inx h mov a,m out hddata inx h dcr b jnz wtloop mvi ae endif ***************************************************************** * * * The following equates relate thera a out hdcmnd cma out hddata out hddata mvi a,rsect ;Read sector command out hdcmnd call process rc xra a  build: lda head ;Build a controller command byte ral ral ral ral lxi h,hddisk ora m xri 0f0h ret hdcur: db 2.4 ana c ;Mask in sector number (0-31) cz getspt ;Translate sector 0 to sector 32 sta hdsect ;Save translated sect lda head out hddata ;Form head byte call hdptr ;Get pointer to current drives track mov a,m ;Form track byte out ,wsect ;Issue write sector command out hdcmnd call process rc mvi a,wfault ana b stc rz xra a ret process Morrow Designs 2D/B * * controller. If the controller is non standard (0F800H) * * only the FDORIG equate need be changed.  out hdcmnd mvi b,seclen/4 lhld hdadd in hddata in hddata rtloop: in hddata ;Move four bytes mov m,a inx h in  0 ;Current logical disk hdadd: dw 0 ;DMA address hddisk: db 0 ;Current physical disk number head: db 0 ;Current physor number (1-32) mvi a,0e0h ;Get the head number ana c rlc rlc rlc sta head ;Save the head number getspt: mvi ahddata ana a mvi b,80h jz zkey mvi b,0 zkey: lda hdsect ;Form sector byte out hddata mov a,b out hddata mvi a  * * * ***************************************************************** if maxfd ne 0 ;Include Discus 2D ? fdorik ;Seek to specified track dw fdssec ;Set sector dw fddma ;Set DMA address dw fdread ;Read a sector dw fdwrite 8h ;Start of I/O registers dreg equ io+1 cmdreg equ io+4 clrcmd equ 0d0h ************************************************ inr a mov c,a ;Make new sector the requested sector pop d call sideone mvi a,80h ;Side two bit ora h ; and sect equ fdorig+18h ;Disk Jockey 2D write routine fdsel equ fdorig+1bh ;Disk Jockey 2D select drive routine fdtstat equ fdorig+2 ;Divide by two sub c ;Subtract sector number push psw ;Save adjusted sector jm sidetwo sidea: pop psw ;Discard adjg equ 0f800H ;Origin of Disk Jockey PROM fdboot equ fdorig+00h ;Disk Jockey 2D initialization fdcin equ fdorig+03h ;Disk J ;Write a sector dw nobad ;No bad sector map ***************************************************************** * ***************** * * * Device Specification Table for the Disk Jockey 2D/B * * * ***************************or mov h,a ret fdldrv: sta fdlog ;Save logical drive mov c,a ;Save drive # mvi a,0 ;Have the floppies been acce1h ;Disk Jockey 2D terminal status routine fdstat equ fdorig+27h ;Disk Jockey 2D status routine fderr equ fdorig+2ah ;Disk usted sector pop b ;Restore sector requested pop d ;Restore address of xlt table sideone:xchg ;hl <- &(translation tockey 2D character input routine fdcout equ fdorig+06h ;Disk Jockey 2D character out routine fdhome equ fdorig+09h ;Disk Joc* * Floppy disk warm boot loader * * * ***************************************************************** fdtran************************************** fddst: db maxfd ;Number of logical drives dw donop ;No warm boot for INSTALL dssed yet ? flopflg equ $-1 ana a jnz flopok mvi b,17 ;Floppies havn't been accessed lxi h,fdboot ;Check if 2D contJockey 2D error, flash led fdden equ fdorig+2dh ;Disk Jockey 2D set density routine fdside equ fdorig+30h ;Disk Jockey 2D seable) dad b ;bc = offset into table mov l,m ;hl <- physical sector mvi h,0 ret sidetwo:call fdgsid ;Check out nkey 2D track zero seek fdseek equ fdorig+0ch ;Disk Jockey 2D track seek routine fdsec equ fdorig+0fh ;Disk Jockey 2D set sec: inx b push d ;Save table address push b ;Save sector # call fdget ;Get DPH for current drive lxi d,10 ;Load DPw fdtran ;Sector translation dw fdldrv ;Select drive 1 dw fdsel2 ;Select drive 2 dw fdlhome ;Home drive dw fdseeroller is installed mvi a,(jmp) clopp: cmp m ;Must have 17 jumps jnz zret inx h inx h inx h dcr b jnz clopp lt side routine fdram equ fdorig+400h ;Disk Jockey 2D RAM address dblsid equ 20h ;Side bit from controller io equ fdorig+3fumber of sides jz sidea ;Single sided pop psw ;Retrieve adjusted sector pop b cma ;Make sector request positive tor routine fddma equ fdorig+12h ;Disk Jockey 2D set DMA address fdread equ fdorig+15h ;Disk Jockey 2D read routine fdwriteH pointer dad d mov a,m inx h mov h,m mov l,a mov a,m ;Get # of CP/M sectors/track ora a ;Clear carry rar  xi d,fdinit ;Initialization sequence lxi h,fdorig+7e2h ;Load address lxi b,30 ;Byte count call movbyt ;Load controllctor size code fdget: lda fdlog ;Return proper DPH lxi d,dphfd0 jmp retdph fdsel2: sta fdlog mov c,a jmp fdsel atus ani dblsid ;Check double sided bit mov m,a ;Save sides flag lxi d,dpb128s ;Base for single sided DPB's jz sidedb 0 ;Side desired db 1 ;Sector desired db 0 ;Track desired db 0 ;Header image, track db 0 ;Sector db 0  ;Get status on current drive sta fdldst ;Save drive status ani 0ch ;Mask in sector size bits push psw ;Used to sel 2D/B dw 1800h ;Head loaded timeout dw 0 ;DMA address db 0 ;Double sided flag db 0 ;Read header flag db 07eh er RAM mvi a,0ffh ;Start 1791 sta dreg mvi a,clrcmd ;1791 reset sta cmdreg mvi a,1 ;Set 2D initialized flag stafdlhome:mvi c,0 ;Select side 0 call fdside jmp fdhome ;Do actual home fdssec: push b ;Save sector number mov a,b ok lxi d,dpb128d ;Base of double sided DPB's sideok: xchg pop d ;(HL) -> DPB base, (DE) -> &DPH.DPB pop psw ;Offset ;Side db 0 ;Sector dw 0 ;CRC fdlog: db 0 fdldst: db 0 ;Floppy drive status byte fdlsid: rept maxfd db 0ffh ect a DPB rar lxi h,xlts ;Table of XLT addresses mov e,a mvi d,0 dad d push h ;Save pointer to proper XLT call ;Drive select constant db 0 ;Drive number db 8 ;Current disk db 0 ;Head loaded flag db 9 ;Drive 0 parameters  flopflg flopok: call flush ;Flush buffer since we are using it lda fdlog ;Select new drive mov c,a call fdsel ca ;Check side select bit rlc ;Move high bit to bit zero ani 1 mov c,a call fdside ;Call select side 0/1 pop b jto correct DPB ral ral ;Make 0, 10, 20, 30 mov c,a mvi b,0 ;Make offset dad b ;(hl) is now a DPB pointer xchg;Number of sides on each drive 0/1 endm endif if (maxfd ne 0) or (maxdm ne 0) *************************************** fdget ;Get pointer to proper DPH pop d lxi b,2 ;Copy XLT pointer into DPH call movbyt lxi d,8 ;Offset to DPB poindb 0ffh ;Drive 0 track address db 9 ;Drive 1 parameters db 0ffh ;Drive 1 track address db 9 ;Drive 2 parameters ll fdlhome ;Recalibrate the drive lxi h,1 ;Select sector 1 of track 2 shld truesec inx h shld cpmtrk xra a ;Makemp fdsec fdgsid: lxi h,fdlsid ;Side flag table lda fdlog ;Drive number push d mov e,a ;Make offset mvi d,0 dad ;Put proper DPB address in DPH.DPB mov m,e inx h mov m,d lxi h,15 ;Offset to DPB.SIZ dad d mov c,m ;Fetch se************************** * * * Xlts is a table of address that point to each of the xlt * * tables for each sector ster in DPH dad d ;HL <- &DPH.DPB push h call fdgsid ;Get pointer to side flag table entry lda fdldst ;Get drive stdb 0ffh ;Drive 2 track address db 9 ;Drive 3 parameters db 0ffh ;Drive 3 track address db 9 ;Current parameters  sure we are doing a read sta rdwr call fill ;Fill in buffer with sector jc zret ;Test for error return call fdstat  d ;Offset to proper entry pop d mov a,m ;Set up flags ora a ret fdinit: dw 0 ;Initialization bytes loaded onto ize. * * * ***************************************************************** xlts: dw xlt128 ;Xlt for 128 byte* * * ************************************************************************* ***********************************6,27,28 db 41,42,43,44,57,58,59,60 db 13,14,15,16,29,30,31,32 db 45,46,47,48 xlt124: db 0 db 1,2,3,4,5,6,7,8 db 25, * The following DPB defines a diskette as 512 byte sectors, * * double density, and single sided. * * * ************************************************** xlt128: db 0 db 1,7,13,19,25 db 5,11,17,23 db 3,9,15,21 db 2,8,14,20,26 ************ * * * The following DPB defines a diskette for 256 byte sectors, * * double density, and single sided.  sectors dw xlt256 ;Xlt for 256 byte sectors dw xlt512 ;Xlt for 512 byte sectors dw xlt124 ;Xlt for 1024 byte sector************************************** * * * The following DPB defines a diskette for 128 byte sectors, * * single 26,27,28,29,30,31,32 db 49,50,51,52,53,54,55,56 db 9,10,11,12,13,14,15,16 db 33,34,35,36,37,38,39,40 db 57,58,59,60,61,6******************************************************************* dpb512s:dw 60 ;CP/M sectors/track db 4 ;BSH db 15 db 6,12,18,24 db 4,10,16,22 xlt256: db 0 db 1,2,19,20,37,38 db 3,4,21,22,39,40 db 5,6,23,24,41,42 db 7,8,25,26,43 * * * ************************************************************************* dpb256s:dw 52 ;CP/M sectors/ts ************************************************************************* * * * Xlt tables (sector skew tables) fdensity, and single sided. * * * ************************************************************************* dpb12,63,64 db 17,18,19,20,21,22,23,24 db 41,42,43,44,45,46,47,48 *********************************************************** ;BLM db 0 ;EXM dw 280 ;DSM dw 127 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 32 ;CKS dw 2 ;OFF db 3 ;512 ,44 db 9,10,27,28,45,46 db 11,12,29,30,47,48 db 13,14,31,32,49,50 db 15,16,33,34,51,52 db 17,18,35,36 xlt512: db 0 rack db 4 ;BSH db 15 ;BLM db 1 ;EXM dw 242 ;DSM dw 127 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 32 ;CKS or CP/M 2.2. These tables * * define the sector translation that occurs when mapping CP/M * * sectors to physical sectors o28s:dw 26 ;CP/M sectors/track db 3 ;BSH db 7 ;BLM db 0 ;EXM dw 242 ;DSM dw 63 ;DRM db 0c0h ;AL0 db 0************** * * * Each of the following tables describes a diskette with the * * specified characteristics. byte sectors ************************************************************************* * * * The following DPB defi db 1,2,3,4,17,18,19,20 db 33,34,35,36,49,50,51,52 db 5,6,7,8,21,22,23,24 db 37,38,39,40,53,54,55,56 db 9,10,11,12,25,2dw 2 ;OFF db 2 ;256 byte sectors ************************************************************************* * *n the disk. There is one skew table * * for each of the possible sector sizes. * * * ***************************** ;AL1 dw 16 ;CKS dw 2 ;OFF db 1 ;128 byte sectors ************************************************************* nes a diskette as 1024 byte sectors, * * double density, and single sided. * * * *******************************s/track db 4 ;BSH db 15 ;BLM db 0 ;EXM dw 561 ;DSM dw 255 ;DRM db 0f0h ;AL0 db 0 ;AL1 dw 64 ;CKS56d:dw 104 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 0 ;EXM dw 486 ;DSM dw 255 ;DRM db 0f0h ;AL0 ddmsdma equ 23h ;Set DMA address intrqc equ 24h ;Set Interrupt request dmhaltc equ 25h ;Halt command bracha equ 26h ;C****************** dpb128d:dw 52 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 1 ;EXM dw 242 ;DSM dw 127 ;1024 byte sectors endif ***************************************************************** * * * The following e****************************************** dp1024s:dw 64 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 0 ;EXM d dw 2 ;OFF db 3 ;512 byte sectors ************************************************************************* * b 0 ;AL1 dw 64 ;CKS dw 2 ;OFF db 2 ;256 byte sectors **********************************************************hannel branch setcha equ 27h ;Set channel address setcrc equ 28h ;Set CRC retry count rdtrck equ 29h ;Read track comman;DRM db 0c0h ;AL0 db 0 ;AL1 dw 32 ;CKS dw 2 ;OFF db 1 ;128 byte sectors *********************************quates relate the Morrow Designs DJDMA * * controller. * * * **************************************************w 299 ;DSM dw 127 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 32 ;CKS dw 2 ;OFF db 4 ;1024 byte sectors ******** * * The following DPB defines a diskette as 1024 byte sectors, * * double density, and double sided. * * * ***************** * * * The following DPB defines a diskette as 512 byte sectors, * * double density, and double sidedd wrtrck equ 2ah ;Write track command serout equ 2bh ;Serial console ouput senabl equ 2ch ;Enable serial input trksiz **************************************** * * * The following DPB defines a diskette as 256 byte sectors, * * double *************** if (maxdm ne 0) or (maxmf ne 0) dmchan equ 50h ;Default channel address dmkick equ 0efh ;Kick I/O port***************************************************************** * * * The following DPB defines a diskette for 128 b*********************************************************************** dp1024d:dw 128 ;CP/M sectors/track db 4 ;BSH . * * * ************************************************************************* dpb512d:dw 120 ;CP/M sectorequ 2dh ;Set number of tracks setlog equ 2eh ;Set logical drives readm equ 0a0h ;Read from controller memory writem equdensity, and double sided. * * * ************************************************************************* dpb2 address rdsect equ 20h ;Read sector command wrsect equ 21h ;Write a sector command gstat equ 22h ;Get drive status yte sectors, * * single density, and double sided. * * * *******************************************************db 15 ;BLM db 0 ;EXM dw 599 ;DSM dw 255 ;DRM db 0f0h ;AL0 db 0 ;AL1 dw 64 ;CKS dw 2 ;OFF db 4   0a1h ;Write to controller memory dmfstp equ 3*341/10 ;Fast stepping rate = 3 ms * 34.1 dmfset equ 15*341/10 ;Fast settlmov c,a ;Make new sector the requested sector pop d call dmside1 mvi a,80h ;Side two bit ora h ; and sector mov  CP/M sectors/track ora a ;Clear cary rar ;Divide by two sub c push psw ;Save adjusted sector jm dmside2 dmsid,a mvi b,0 dad b xchg ;Put DPB address in DPH mov m,e inx h mov m,d lxi h,15 dad d mov c,m dmget: lda dmlorv ;Select drive 1 dw dmselr ;Select drive 2 dw dmhome ;Home drive dw dmseek ;Seek to specified track dw dmssec call dmget pop d lxi b,2 ;Number of bytes to move call movbyt ;Move the address of XLT lxi d,8 ;Offset to DPB poining rate = 15 ms * 34.1 n$dubl equ 80h ;Double density n$2side equ 40h ;2 sided drive serin equ 03eh ;Address of seh,a ret dmldrv: sta dmlog call dminit ;Test for a drive jc zret lxi h,1 ;Select sector 1 of track 2 shld trueseea:pop psw ;Discard adjusted sector pop b ;Restore sector requested pop d ;Restor address of xlt table dmside1:xchg g lxi d,dphdm0 jmp retdph ; ; The current drive is double sided. Thus is it safe to set the ; stepping rate to 3 ms wi ;Set sector dw dmdma ;Set DMA address dw dmread ;Read a sector dw dmwrite ;Write a sector dw nobad ;No bad secter dad d ;HL <- &DPH.DPB push h call dmstat ani 20h ;Check double sided bit lxi d,dpb128s ;Base for single sidedrial input data ***************************************************************** * * * Device Specification Table fc inx h shld cpmtrk xra a ;Make sure we are doing a read sta rdwr call fill ;Flush buffer and refill jc zret ; ;hl <- &(translation table) dad b ;bc = offset into table mov l,m ;hl <- physical sector mvi h,0 ret dmside2:cath 15 ms settling. ; sethigh:lhld dmlog ;Get the current drive number mvi h,0 dad h ;Ten bytes per parameter table etor map dmselr: sta dmlog mvi b,0 ;8 inch logical drives start at zero jmp dmsel2 dmtran: inx b push d ;Save tab DPB's jz dmsok call sethigh ;Set controller for fast steping lxi d,dpb128d ;Base of double sided DPB's dmsok: xchg or the Disk Jockey DMA floppy * * * ***************************************************************** if maxdm ne 0Test for error return call dmstat ;Get status on current drive ani 0ch ;Mask in sector size bits push psw ;Used toll dmstat ani 20h jz dmsidea pop psw ;Retrieve adjusted sector pop b cma ;Make sector request positive inr a ntry mov d,h mov e,l dad h dad h dad d lxi d,dparam+1 ;Parameter table address dad d ;Skip the track size byte le address push b ;Save sector # call dmget lxi d,10 dad d mov a,m inx h mov h,m mov l,a mov a,m ;Get # of ;HL <- DBP base, DE <- &DPH.DPB pop d ;Restore DE (pointer into DPH) pop psw ;Offset to correct DPB ral ral mov c dmdst: db maxdm ;Number of logical drives dw donop ;No warm boot for INSTALL dw dmtran ;Sector translation dw dmld select a DPB rar lxi h,xlts ;Table of XLT addresses mov e,a mvi d,0 dad d push h ;Save pointer to proper XLT   mvi m,0 ;Force reparamitization of this drive inx h ;Offset to the Stepping rate constant mvi m,(low dmfstp) ;Fast stmseek mfsel2: sta mflog mov c,a ;Get proper physical configuration byte mvi b,0 lxi h,mfscon dad b mov a,m st,80h ;Set high bit for double sided select jmp dmssec dblflg: db 0 mfseek: xra a ;Clear double sided select sta dby jc zret ; status on track 0 pop psw ora a jnz mfl9 ;Non zero mvi a,90h ;Double density default configuraber of logical drives dw donop ;No warm boot for INSTALL dw mftran ;Sector translation dw mfldrv ;Select drive 1 dproper physical configuration byte mov c,a mvi b,0 lxi h,mfscon dad b mvi a,n$dubl mov m,a sta mfpcon lxi h,1 epping rate constant inx h mvi m,(high dmfstp) lxi d,5 ;Skip over the reserved fields dad d mvi m,(low dmfset) ;Fasa mfpcon mov a,c ;Shhh, pretend that nothing happened mvi b,4 ;5 1/4 inch drives start at drive 4 jmp dmsel2 mftrlflg lda mfpcon ani n$2side jz dmseek ;Only single sided mov a,c ;Move selected track in (a) sbi 35 ;Subtract tion call dmstat ;If zero then determine sector size ani 80h ;Check density bit jnz mfl9 ;Its double density mvi aw mfsel2 ;Select drive 2 dw dmhome ;Home drive dw mfseek ;Seek to specified track dw mfssec ;Set sector dw dmdma ;Select sector 1 of track 0 shld truesec dcx h shld cpmtrk xra a ;Make sure we are doing a read sta rdwr call fit settling rate constant inx h mvi m,(high dmfset) call dmparm ;Set drive parameters for the SA850 ret endif **an: lda mfpcon ani n$dubl lxi h,mfxltd ;Point to double sided sectran table jnz mftdubl ;Single density sector translatby track by number of tracks jc dmseek ;Less than track 35 mov d,a ;Save adjusted track number mvi a,34 sub d ;A,10h ;Single density configuration byte mfl9: mov c,a ;Move configuration byte into (c) lxi h,mfs ;Address of confi ;Set DMA address dw dmread ;Read a sector dw dmwrite ;Write a sector dw nobad ;No bad sector map mfssec: dcr cll ;Flush buffer and refill jc zret ;Test for error return lda buffer+5ch ;Get diskette configuration byte push psw*************************************************************** * * * Drive specification table for DJDMA 5 1/4 inch drion lxi h,mfxlts mftdubl:dad b ;Add offset sector number to table mov l,m ;Pick up sector number from table mvi h,0 djust to count tracks back out mov c,a ;Resave new track number mvi a,0ffh ;Set double sided flag sta dblflg jmp dguration table -> (hl) mfl2: mov a,m ;Get an entry ora a ;Check for end of the table jz zret ;Yes, select error cmp ;Minnie floppy sectors start at zero lda dblflg ;Get double sided flags ora a jz dmssec ;Nope, single sided mvi b ;Save configuration byte lxi h,1 shld cpmtrk ;Load track 1 sector 1 call fill ;DJDMA firmware returns single densitives * * * ***************************************************************** if maxmf ne 0 mfdst: db maxmf ;Num ;MSB of sector number equal 0 ret mfldrv: sta mflog call dminit ;Test for a controller jc zret lda mflog ;Get   c ;Check if entry matches selected drive jz mfl3 inx h ;Skip onfiguration byte inx h ;Skip drive type inx h ;Sk40 track) db n$dubl+n$2side ;Double density, 35 tracks, two sided dw dpbmf3 ;2K groups db 0 ;End of configuration t db 0b0h ;North Star CP/M 2.x db n$dubl ;Double density, 35 tracks, one sided dw dpbmf2 ;2K groups db 0f0h ;Noc inx h mov m,a out dmkick tests ora m jz tests ret dminit: lxi h,dmchan ;See if controller will halt mvi m,dmht status pop h ani 80h ;Check density bit mvi c,3 ;512 byte sectors rnz mvi c,2 ;256 byte sectors ret mfgdp******************** dmsel2: mov c,a ;Move drive into (c) lxi h,dmchan mvi m,setlog ;Set logical drives inx h mov ip DPB address inx h jmp mfl2 mfl3: inx h mov a,m ;Pick up drive type sta mfpcon mov e,a push h lda mflog able mfxltd db 1, 2, 3, 4 db 21,22,23,24 db 5, 6, 7, 8 db 25,26,27,28 db 9,10,11,12 db 29,30,31,32 db 13,14,15rth Star CP/M 2.x db n$dubl+n$2side ;Double density, 35 tracks, two sided dw dpbmf3 ;2K groups db 0e5h ;North Star altc inx h mvi m,0 out dmkick ;Start controller lxi d,0 ;Set up timeout counter dminwt mov a,m ora a jnz dmiok h lda mflog lxi d,dphmf0 jmp retdph mfpcon: db 0 ;Physical configuration byte mflog: db 0 mfscon: db 0, 0, 0, 0 ;Sm,b ;Drive in (b) push b call docmd pop b jmp dmsel dmssec: push b ;Save sector number mov a,b rlc ani 1  ;Get proper physical configuration byte mov c,a mvi b,0 lxi h,mfscon dad b mov m,e pop h inx h mov a,m inx ,16 db 33,34,35,36 db 17,18,19,20 db 37,38,39,40 mfxlts db 1, 2 db 3, 4 db 5, 6 db 7, 8 db 9,10 db 11,12CP/M 1.4 db n$dubl ;Double density, 35 tracks, one sided dw dpbmf1 ;1K groups db 0a0h ;North Star CP/M 2.x (fake  ;Controller has responded dcx d ;Bump timeout counter mov a,d ora e jnz dminwt stc ;Set error flag ret dmiaved physical configuration bytes mfs: db 10h ;North Star CP/M 1.4 db 0 ;Single density, 35 tracks, one sided dw dpbmmov c,a call dmside pop b jmp dmsec dmdma lxi h,dmchan ;Default channel address mvi m,dmsdma ;Set DMA address inxh mov h,m mov l,a ;DPB address -> (hl) push h ;Save DPB address call mfgdph ;Get DPH lxi d,10 ;Offset to DPB a db 13,14 db 15,16 db 17,18 db 19,20 endif ***************************************************************** * 40 track) db n$dubl ;Double density, 35 tracks, one sided dw dpbmf2 ;2K groups db 0d0h ;North Star CP/M 2.x (fake ok push h ;Set drive parameters call dmparm pop h dcx h ;Back to start of command mvi m,setcrc ;Disable monitor if0 ;1K groups db 90h ;North Star CP/M 1.4 db n$dubl ;Double density, 35 tracks, two sided dw dpbmf1 ;1K groups  h mov m,c ;Low byte first inx h mov m,b ;High byte next docmd xra a inx h mov m,a docmd2 inx h mvi m,dmhaltddress in DPH dad d pop d mov m,e ;Store DPB address in DPH inx h mov m,d call mfgdph push h call dmstat ;Ge * * Common routines for the DJDMA with 8 and 5 1/4 inch drives * * * ********************************************* nx h mvi m,1 xra a jmp docmd2 ;Do command ; ; Set floppy drive parameters ; ; This routine reads the dparam table  ;Move around to bit 7 mov c,a ;Resave in (c) lda llss ani 7fh ;Mask out old side select bit jmp stores dmsel: moBump parameter table pointer dad b xchg lxi b,16 ;Bump controller tables pointer dad b xchg pop psw ;Retrieve ove to bit 4 ora m ;Put together with lower drive bits ora c mov c,a inx h mvi a,10h ;Double density bit ana m  dcr m ;Set to calibrated mode (0ffh) dcx h ;Back up to the track size byte shld dmntrk ;Set the number of tracks po----------+ | ; Drive select LSB --------------------------+ ; dmstat lxi h,dmchan mvi m,gstat ;Set up read status iand if the a drive has not ; previously been calibrated then that drives track count, ; stepping rate, and head settling time v a,c ;Move drive into (a) sta lldrv dmden: ret ;Double density only ; ; Return status in the (a) register in the fodrive count dcr a ;Bump count jnz dmstr0 ;Set up next drive ret dmhome xra a mov c,a ;Put a zero into (c) for rlc ;20h rlc ;40h rlc ;80h for density bit ora c mov c,a inx h mvi a,3 ;Sector length mask ana m ;Aninter inx h inx h shld dmspar ;Set the stepping constants pointer xchg ;Set the local parameter table pointer shlnx h lda lldrv ;Get last selected drive mov m,a ;Store drive in command inx h ;Skip over returned status inx h iare loaded. ; dmparm: mvi a,8 ;Eight drives lxi d,1340h ;Start with drive 0's table lxi h,dparam+1 ;Drive parameterrm: ; ; 7 6 5 5 3 2 1 0 ; ^ ^ ^ ^ ^ ^ ^ ^ ; Density --------------+ | | | | | | | ; Side select -- track zero dmseek mov a,c ;Enter with track in (c) sta lltrk ;Save for use later ret dmsec lda llss ;Load sectod in rlc ;Move to bits 2 & 3 rlc ora c mov c,a inx h mvi a,4 ;Mask for double sided bit ana m rlc ;8 rd dmloc0 inx h ;Offset to the stepping parameters inx h inx h inx h shld dmloc1 lxi h,dmwcon ;Write the drive connx h call docmd ;Issue command lda llss ;Get side bit of last operation ani 80h rrc ;Move to bit 7 mov c,a lx table dmstr0: push psw ;Save the drive count mov a,m ;Load flags ora a ;Does the drive need to be calibrated? jn-----------+ | | | | | | ; Double sided ---------------+ | | | | | ; 5 1/4 -------------------------+ | | | | r ani 80h ;Save side select bit stores ora c sta llss ret dmside: mov a,c ;Move side bit into (a) ani 1 rrc lc ;10 rlc ;20 ora c ret dmwrite mvi a,wrsect db 01 ;Ugh... dmread mvi a,rdsect lxi h,dmchan lxi d,lltrkstants out lxi d,17 ;Halt status offset call dmdoit pop d ;Retrieve the table pointers pop h dmstr1: lxi b,10 ;i h,dmchan+1 ;Point to drive mov a,m ;Load drive ora c ani 4 ;Mask upper drive select bit for 5 1/4 rlc rlc ;Mz dmstr1 ;No, do not fiddle around push h ;Save the parameter table pointer push d ;Save the controllers table pointer; Sector size MSB ------------------+ | | | ; Sector size LSB ---------------------+ | | ; Drive select MSB ------------- -1 mvi b,4 cload mov m,a inx h inx d ldax d dcr b jnz cload dcx h call docmd lda dmchan+4 cpi 80h cmc rcl equ 30 ;Recalibrate step delay headdly equ 0 ;Settle delay (0-25.5 milliseconds) endif if st412 ;Specifications for********** * * * The follwing equates are for the HDDMA hard disk controller * * * ***************************omp, high current band2 equ 0c0h ;Precomp, high current band3 equ 80h ;precomp, low current track0 equ 1 ;Track zero statu status jz dmwait ret dmwcon: db writem ;Write track size dmntrk: dw 0 ;Number of tracks + desync db 0 ;X-addr ;Define controller commands dmaread equ 0 ;Read sector dmawrit equ 1 ;Write sector dmarhed equ 2 ;Find a sector dmaet ; ; Execute a DJDMA command, no command status is returned ; ; Entry: ; DE = offset to the halt status ; HL = point a Seagate ST412 cyl equ 306 heads equ 4 precomp equ 128 lowcurr equ 128 stepdly equ 0 steprcl equ 30 headdly equ 0 end************************************** if maxmw ne 0 ;HDDMA controller present ? if st506 ;Specifications for a Seagate Ts wflt equ 2 ;Write fault from drive dready equ 4 ;Drive ready sekcmp equ 8 ;Seek complete ****************************ess dw 2 ;Two bytes dmloc0: dw 0 ;Local controller address db writem ;Write stepping rate data dmspar: dw 0 ;Poiwhed equ 3 ;Write headers (format a track) dmalcon equ 4 ;Load disk parameters dmassta equ 5 ;Sense disk drive status dmaner to the start of the command ; ; Returns: ; nothing ; dmdoit: mvi a,bracha ;Branch channel command sta dmchan shlif if cm5619 ;Specifications for an CMI 5619 cyl equ 306 heads equ 6 precomp equ 128 lowcurr equ 128 stepdly equ 3 stechnology 506 cyl equ 153 ;Number of cylinders heads equ 4 ;Number of heads per cylinder precomp equ 64 ;Cylinder to start************************************* * * * Drive Specification Table for the HD DMA hard disk controller * * *nter to the stepping parameters db 0 dw 8 dmloc1: dw 0 db dmhaltc ;Controller halt db 0 ;Status ; ; Driver vaoop equ 6 ;Null controller operation reset equ 54h ;Reset controller attn equ 55h ;Send a controller attention chan eqd dmchan+1 ;Load command vector xra a ;Clear extended address sta dmchan+3 dad d ;Offset to the halt status mov meprcl equ 30 headdly equ 30 endif sectsiz equ 7 ;Sector size code (must be 7 for this IBIOS) ; 0 = 128 byte sectors write precomensation lowcurr equ 128 ;Cylinder to start low current stepdly equ 30 ;Step delay (0-12.7 milliseconds) stepr ***************************************************************** mwdst: db maxmw*mwlog ;Number of logical drives dw donoriables ; lltrk db 0 llss db 1 lldrv db 0 dmlog db 0 endif *******************************************************u 50h ;Default channel address stepout equ 10h ;Step direction out stepin equ 0 ;Step direction in band1 equ 40h ;No prec,a ;Clear the halt status indicator out dmkick ;Start the controller dmwait: ora m ;Wait for the operation complete ; 1 = 256 byte sectors ; 3 = 512 byte sectors ; 7 = 1024 byte sectors (default) ; f = 2048 byte sectors  p ;No warm boot for INSTALL dw mwtran ;Sector translation dw mwldrv ;Select logical drive 1 (First time select) dw mwdrlow rate) inx h mvi m,headdly ;Head settle delay call mwissue ;Do load constants again call mwptr ;Get pointer to currdad h dad h dad d ;(hl) = pointer to DPH mvi c,4 ;Return sector size of 1024 ret mwdrv sta mwcurl call mwdlog mp to proper track lxi h,0 ;Clear step counter shld dmastep ret mwdma mov h,b ;Set DMA address mov l,c shld dmadma Designs Hard Disk DMA controller. * * * ***************************************************************** mwldrvld cylinder word mov h,b shld dmarg0 ;Set command channel cylinder number mov a,d inr a lxi h,0ffffh jnz mwskip0 v ;Select logical drive 2 (General select) dw mwhome ;Home current selected drive dw mwseek ;Seek to selected track dw ent cylinder number mvi m,0ffh ;Fake at cylinder 65535 for max head travel inx h mvi m,0ffh lxi b,0 ;Seek to cylinder ov a,c sta mwdrive ;Save new selected drive mwsel mvi a,dmanoop jmp mwprep ;Execute disk command mwdlog: mvi c,0 mwll ret mwsec mov a,c ;Load sector number dcr a ;Range is actaully 0-16 call mwdspt ;Figure out head number -> (c) ad sta mwcurl ;Save current logical drive call mwreset ;Reset controller card jc zret ;Controller failure lda mwcurl mvi c,stepout jmp mwskip mwskip0:mov h,b ;(hl) = new track, (de) = old track mov l,c call mwhlmde mvi c,stepout momwsec ;Select sector dw mwdma ;Set DMA address dw mwread ;Read a sector dw mwwrite ;Write a sector if heads > 2 ;Tes0 call mwseek ;Recal slowly jmp mwreset ;Back to fast stepping mode mwbad: lxi h,mwbtab ;Return pointer to bad sector lx: sui mwlog rc inr c jmp mwllx mwstat mvi a,dmassta ;Sense status operation code jmp mwprep ;Execute disk command i mwspt ;Make sector number sta mwsectr mov a,c sta mwhead ;Save head number ret mwdspt mvi c,0 ;Clear head countecall mwdrv ;Select drive jc zret ;Select error call mwstat ;Get drive status ani dready ;Check if drive ready jnz v a,h ani 80h ;Check hit bit for negitive direction jnz mwsout ;Step in mvi c,0 jmp mwskip mwsout: call mwneghl mwskt if drive is big enough for a bad spot map dw mwbad ;Return bad sector map info else dw nobad endif ***************ocation ret mwbtab: dw 0 ;Track 0 dw 19 ;Head 2, sector 0 = (2 * SPT + 0) + 1 mwseek call mwptr ;Get track pointer mwhome call mwreset ;Reset controller, do a load constants lxi h,dmarg1 ;Load arguments mvi m,steprcl ;Load step delay (sr mwdsptx sui mwspt ;Subtract a tracks worth of sectors rc ;Return if all done inr c ;Bump to next head jmp mwdsptx zret call mwhome ;Home drive lxi d,dphmw0 ;Start of hard disk DPH's lda mwcurl mov l,a mvi h,0 dad h dad h ip: shld dmastep lda mwdrive ora c sta dmasel0 mvi a,dmanoop ;No-operation command for the channel call mwprep ;Ste************************************************** * * * The following are the lowest level drivers for the Morrow * * mov e,m ;Get old track number inx h mov d,m dcx h mov m,c ;Store new track number inx h mov m,b mov l,c ;Bui  mwreset lhld chan ;Save the command channel for a while shld tempb lda chan+2 sta tempb+2 out reset ;Send reset puls 7 ;3 bits of head select rlc ;Shove over to bits 2 - 4 rlc ora c ;Add on low current and precomp bits mov c,a ldae channel pointer shld chan lda tempb+2 sta chan+2 pop psw ret mwread mvi a,dmaread ;Load disk read command jmp m command, handle timeouts + errors endif lxi h,dmastat ;Clear status byte mvi m,0 out attn ;Start the controller y ;Head settle delay inx h mvi m,sectsiz ;Sector size code inx h mvi m,dmalcon ;Load constants command **************pop h pop b inx h ;Bump command channel pointer dcr c jnz mwerr mvi c,0ah ;Terminate with a CRLF call ocout mvi e to controller lxi h,dmachan ;Address of command channel shld chan ;Default channel address xra a sta chan+2 ;Clear e mwdrive ;Load drive address ora c ;Slap in drive bits sta dmasel1 ;Save in command channel head select lda mwsectr ;Lwprep mwwrite mvi a,dmawrit ;Load disk write command mwprep: sta dmaop ;Save command channel op code mvi c,band1 lhlxi d,0 ;Time out counter (65536 retries) mwiloop mov a,m ;Get status ora a ;Set up CPU flags rm ;Return no error (car*********************************************** lxi h,0 ;wait for controller!!!!!!!!!!!!! rsdelay dcx h ;by counting downc,0dh call ocout pop psw ;Restore error status ret dspout: call spout ;Print two spaces spout: mvi c,' ' ;Print a sxtended address byte shld bios ;Set up a pointer to the command channel sta bios+2 lhld dmarg0 ;Save the track number oad sector address sta dmarg3 if 1 ;Set to 1 for MW error reporter mwissue call mwdoit ;Do desired operation rnc ;Dld dmarg0 lxi d,precomp call mwhlcde jc mwpreps mvi c,band2 lxi d,lowcurr call mwhlcde jc mwpreps mvi c,bandry reset) stc rnz ;Return error status xthl ;Waste some time xthl xthl xthl dcx d ;Bump timeout counter mov 65536 mov a,h ora l jnz rsdelay ************************************************************* call mwissue ;Do lopace jmp ocout hexout: push psw ;Poor persons number printer rrc rrc rrc rrc call nibout pop psw nibout: ani push h lxi h,dmasel1 ;Load arguments lda mwdrive ;Get the currently selected drive ori 03ch ;Raise *step and *dir mov o nothing if no error push psw ;Save error info call hexout ;Print status call dspout ; and a space lxi h,dmachan 3 ;cylinder > low_current mwpreps lda mwhead ;Load head address sta dmarg2 cma ;Negative logic for the controller ani a,d ora e jnz mwiloop ;Loop if still busy stc ;Set error flag ret mwptr lda mwdrive ;Get currently select drivesad constants pop h ;Restore the track number shld dmarg0 push psw ;Save status lhld tempb ;Restore memory used for th0fh adi '0' cpi '9'+1 jc nibok adi 27h nibok: mov c,a jmp ocout mwdoit equ $ else mwissue equ $ ;Do a diskm,a ;Save in drive select register lxi d,5 ;Offset to dmarg1 dad d mvi m,stepdly ;Load step delay inx h mvi m,headdl mvi c,16 ;16 bytes of status mwerr: push b push h mov a,m call hexout ;Print a byte of the status line call spout   track address rlc mov e,a mvi d,0 lxi h,mwtab dad d ;Offset into track table ret mwtran: mov h,b mov l,c inw 0 ;Alternate track altsec: dw 0 ;Alterante sector lastdrv:db 0 ;Last selected drive ****************************************************** * * * IBIOS ram locations that don't need initialization. * * * ************************rks equ 243 ;Total data tracks endif if m20 ne 0 hdsectp equ 672 hdtrks equ 243 endif if m26 ne 0 hdsectp equan equ $ ;Command channel area dmasel0 db 0 ;Drive select dmastep dw 0 ;Relative step counter dmasel1 db 0 ;Head select yte sectors per cylinder. * * * * hdtrks is the total number of data cylinders. Eg. it is * * the number of cylidersx h ret mwneghl:mov a,h cma mov h,a mov a,l cma mov l,a inx h ret mwhlmde:xchg call mwneghl xchg dad******************************* * * * DPB and DPH area. * * * ************************************************************************************ cpmsec: dw 0 ;CP/M sector # cpmdrv: db 0 ;CP/M drive # cpmtrk: dw 0 ;CP/M tr 1024 hdtrks equ 201 endif ldsk set 0 ;Use non-standard partitioning tracks set hdtrks/hdlog ;Number of tracks per partdmadma dw 0 ;DMA address db 0 ;Extended address dmarg0 db 0 ;First argument dmarg1 db 0 ;Second argument dmarg2 db 0 ; on the drive minus the number of * * cylinders that are used for the system. If the number of * * 'system tracks' is not one d ret mwhlcde:mov a,h cmp d rnz mov a,l cmp e ret mwtab equ $ ;Collection of track addresses rept maxmw ********************** if maxhd ne 0 dphdsk set 0 ;Generate DPH's for the hdc3 hard disks rept maxhd ldsk set 0 repack # truesec:dw 0 ;Physical sector that contains CP/M sector error: db 0 ;Buffer's error status flag bufdrv: db 0 ;Drivition dsm set hdsectp/8*tracks/4-1 ;Number of groups per partition off set 1 rept hdlog dpbgen hd,%ldsk,%hdsectp,5,31,1,Third argument dmarg3 db 0 ;Fourth argument dmaop db 0 ;Operation code dmastat db 0 ;Controller status byte dmalnk dw dma then the initial value of * * 'off' should be adjusted accordingly. * * * * hdtrks = tracks - 1 * * db 0ffh ;Initialize to (way out on the end of the disk) db 0ffh endm db 0ffh mwcurl db 0 ;Current logical drive mwdrt hdlog dphgen hd,%dphdsk,dpbhd,%ldsk ldsk set ldsk+1 dphdsk set dphdsk+1 endm endm if hdpart ne 0 ;Use non-standarde that buffer belongs to buftrk: dw 0 ;Track that buffer belongs to bufsec: dw 0 ;Sector that buffer belongs to alttrk: d%dsm,511,0ffh,0ffh,0,%off,3 off set off+tracks ldsk set ldsk+1 endm else ;Else use standard DPB's if m26 ne 0 dpbchan ;Link address to next command channel db 0 ;extended address endif ********************************************** ***************************************************************** if m10 ne 0 hdsectp equ 336 ;Sectors per track hdtive db 0ffh ;Currently selected drive mwhead db 0 ;Currently selected head mwsectr db 0 ;Currently selected sector dmach partitioning ***************************************************************** * * * hdsectp is the number of 128 b  hd0 dw 1024 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2015 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ff 3, 7, 0, 0a4h, 63, 0c0h, 0, 16, 2, 3 dpbgen mf, 2, 40, 4, 15, 1, 051h, 63, 80h, 0, 16, 2, 3 dpbgen mf, 3, 40, 4, 15, 1,1 dw 672 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2036 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh  ldsk set ldsk+1 endm endm if mwpart ne 0 ;Generate DPB's for a HDDMA hard disk ldsk set 0 ;Use non-standard partit 1 ;EXM dw 1269 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 1 ;OFF db 3 ;SECSIZ dpbhd1 dw 3 number of data cylinders. * * mwtrks = tracks - 1 * * * ******************************************************h ;AL1 dw 0 ;CKS dw 1 ;OFF db 3 ;SECSIZ dpbhd1 dw 1024 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM 0a9h, 63, 80h, 0, 16, 2, 3 dn set 0 rept maxmf dphgen mf,%dn,dpbmf,%dn dn set dn+1 endm endif if maxfd ne 0 ;AL1 dw 0 ;CKS dw 98 ;OFF db 3 ;SECSIZ dpbhd2 dw 672 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM ioning tracks set mwtrks/mwlog ;Number of tracks per partition dsm set mwsectp/8*tracks/4-1 ;Number of groups per partition o36 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 1280 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 *********** if st506 ne 0 mwsecpt equ 288 ;Sectors per track mwtrks equ 152 ;Total data tracks endif if st412 ne dw 2015 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 64 ;OFF db 3 ;SECSIZ dpbhd2 dw 1024 ;Cdn set 0 rept maxfd dphgen fd,%dn,0,0 dn set dn+1 endm endif if maxdm ne 0 dn set 0 rept maxdm dphgen dm,%dn,0dw 1028 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 195 ;OFF db 3 ;SECSIZ endif endif endifff set 1 rept mwlog dpbgen mw,%ldsk,%mwsecpt,5,31,1,%dsm,1023,0ffh,0ffh,0,%off,4 off set off+tracks ldsk set ldsk+1 en dw 0 ;CKS dw 122 ;OFF db 3 ;SECSIZ endif if m20 ne 0 dpbhd0 dw 672 ;CP/M sectors/track db 5 ;BSH db 31 ;BL 0 mwsecpt set 288 mwtrks set 305 endif if cm5619 ne 0 mwsecpt set 432 mwtrks set 305 endif dphdsk set 0 ;GeP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2047 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ,0 dn set dn+1 endm endif if maxmw ne 0 ***************************************************************** *  ;End of HD DPH's and DPB's if maxmf ne 0 dpbgen mf, 0, 20, 3, 7, 0, 04fh, 63, 0c0h, 0, 16, 3, 2 dpbgen mf, 1, 40,dm else ;Use standard partitioning off set 1 ;Initial system track offset trkoff set 8192/(mwsecpt/8)+1 ;The number M db 1 ;EXM dw 2036 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 1 ;OFF db 3 ;SECSIZ dpbhdnerate DPH's for the HDDMA hard disks rept maxmw ldsk set 0 rept mwlog dphgen mw,%dphdsk,dpbmw,%ldsk dphdsk set dphdsk+1 ;CKS dw 127 ;OFF db 3 ;SECSIZ endif if m10 ne 0 dpbhd0 dw 336 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db* * mwsectp is the number of 128 byte sectors per cylinder. * * mwsectp = 72 * heads * * * * mwtrks is the total! of tracks in a partition blocks set mwsecpt/8*mwtrks ;The number of blocks on the drive psize set trkoff*(mwsecpt/8) ;The numb lxi d,badmap ;Clear out bad map stax d lxi h,badmap+1 lxi b,9*badsiz ;32 map entries call movbyt mvi m,0ffh ;*********************** insetu: lxi sp,100h ;Set up a nice stack lxi h,buff mov a,m ;Get the text buffer contents o ;Bump to the next character mov a,m ;Get a character from the message ora a ;Test for the end of the message jz prhd * * All code placed here (the disk deblocking buffer) will dissapear * * the first time a disk read/write call is exe H: DJDMA 5 1/4" drive 2 ; I: DJDMA 5 1/4" drive 3 ; J: HDDMA M10 drive 0, partition A ; L: HDDMA M10 drive 0, partition B ;er of blocks in a partition ldsk set 0 rept blocks/8192 ;Generate some 8 megabyte DPB's dpbgen mw,%ldsk,%mwsecpt,5,31,1,2End marker xra a ;Select disk A sta cpmdrv lxi h,buff ;Set up initial DMA address call setdma xra a ;A <- 0 ra a ;Test for no flags jz inse0 ;Drive names default to O:, P: sui 'A' ;Convert to binary drive value cpi 16 ;Tes1 ;Skip at end cpi '~' ;Drive name marker jnz prhd0 ;Check out the next character mov m,d ;Load a name inr d ;cuted. However, it * * is safe to place one time initialization code here. * * * ********************************* ... ; prhead: lxi h,prmpt0 ;Print a login message call prmesg lda dlocal ;Print host drives before local drives mo047,1023,0ffh,0ffh,0,%off,4 off set off+trkoff blocks set blocks-psize ldsk set ldsk+1 endm blocks set blocks/4 if block sta bufsec ;Set buffer to unknown state sta bufwrtn ;Set buffer not dirty flag sta error ;Clear buffer error flag t for legal values jnc inse0 ;Use default configuration if not legal sta dlocal ;Bottom of the local drive list inx h Bump the name mov a,d ;Test for drive overflow cpi 'A'+17 ;16 drives max jnc prhd1 ;Skip on overflow jmp prhd0 ;**************************************** ************************************************************************* * v e,a ;Number of drives mvi d,0 ;External drive 0 mvi c,0 ;Start at host drive 0 ('A:') call prhost ;Print the hoss gt 256 ;If there is any stuff left, then use it blocks set blocks-1 dpbgen mw,%ldsk,%mwsecpt,5,31,1,%blocks,1023,0ffh,0ffh,jmp owboot ;Do host warm boot ; ; Print the disk configuration message. ; ; A: Host system drive B: ; B: DJDMA 8" drive ;Bump to the next character inse0: mov a,m ;Test the message flag cpi 'X' cnz prhead ;Print the header if no x flagPress on to the next character prhd1: mvi m,0 ;Terminate the message lxi h,prmpt1 ;Print the local configuration call  * * Set up the INSTALL package variables, set up the IBIOS * * * **************************************************t lines lxi h,prmpt1-1 ;Replace all the '~'s with names lda dlocal ;Starting drive adi 'A' mov d,a prhd0: inx h 0,%off,4 endif endif endif buffer equ $ ************************************************************************* * 0 ; C: DJDMA 8" drive 1 ; D: DJDMA 8" drive 2 ; E: DJDMA 8" drive 3 ; F: DJDMA 5 1/4" drive 0 ; G: DJDMA 5 1/4" drive 1 ;" prmesg lxi h,dlocal mov c,m ;Load the starting host drive mov a,c ;Figure the starting external drive adi maxlog m/10+'@', '.', (revnum mod 10) + '0' db '.', acr, alf, alf, 0 prmpt1: equ $ ;Local drive configuration prompt dn set 1 a drive name msdrv set '0' ;;Drive counter rept ndrive mspart set 'A' ;;Partition counter rept npart db '~: ', &dnaMA 8"', maxdm, 1 endif if dn eq mforder ;Generate the DJDMA 5 1/4 message msprnt 'DJDMA 5 1/4"', maxmf, 1 endif dn call prmesg pop d pop b inr c ;Bump the host drive name inr d ;Bump the external drive name dcr e ;Bump the dr endif if st412 ne 0 msprnt 'HDDMA + M10', maxmw, mwlog endif if cm5619 ne 0 msprnt 'HDDMA + M16', maxmw, mwlog end mov d,a mvi a,16 ;Figure the number of drives sub d jc prhd2 ;Skip if our drives went past drive P: mov e,a call  ;Generate the drive messages rept numprd ;Cover all of our products if dn eq hdorder ;Generate the HDCA's message me, ' drive ', msdrv ;;Print name and drive # if npart gt 1 ;;Print partition #'s only if > 1 parts db ', partition ', mspa set dn+1 endm db 0 ;End of message prmpt2: db ' : Host system drive ' prmpt3: db ' :', acr, alf, 0 db 0,0ffh,0 ive count jmp prhost ; ; Print a NULL terminated string via CP/M's conout routine ; prmesg: mov a,m ;Test for the enif endif if dn eq fdorder ;Generate the 2D/B message if fdorig eq 0e000h msprnt 'DJ2D/B @ E000', maxfd, 1 else ifprhost prhd2: ret ; ; Print a the assignment lines, C = starting host drive, ; D = Starting external drive, E = number o if m10 ne 0 if m10m ne 0 msprnt 'HDCA + Memorex M10', maxhd, hdlog else msprnt 'HDCA + Fujitsu M10', maxhd, hdlog enrt endif db acr, alf ;;End of the configuration line mspart set mspart+1 ;;Bump the partition counter endm msdrv set m ds 512-($-buffer) ;Buffer for 512 byte sectors if (maxfd ne 0) or (maxdm ne 0) or (maxmw ne 0) ds 512 ;Additional sd of the string ora a rz ;Return if done push h ;Save the character pointer mov e,a ;Print a character via CP/M  fdorig eq 0f000h msprnt 'DJ2D/B @ F000', maxfd, 1 else if fdorig eq 0f800h msprnt 'DJ2D/B @ F800', maxfd, 1 else msf drives ; prhost: mov a,e ;Test the count ora a rz ;Return if done mov a,d ;Load the External drive name adidif endif if m20 ne 0 msprnt 'HDCA + Fujitsu M20', maxhd, hdlog endif if m26 ne 0 msprnt 'HDCA + Shugart M26', maxhdsdrv+1 ;;Bump the drive counter endm endm prmpt0: db acr, alf, 'Morrow Designs installable IBIOS, revision ' db revnupace for 1k sector devices endif ***************************************************************** * * * Each bad  mvi c,cpmout call bdos pop h inx h ;Bump the character pointer jmp prmesg msprnt macro dname, ndrive, npart ;Printprnt 'DJ2D/B @ ????', maxfd, 1 endif endif endif endif if dn eq dmorder ;Generate the DJDMA 8 message msprnt 'DJD 'A' sta prmpt2 mov a,c ;Load the host drive name adi 'A' sta prmpt3 push b ;Print a line push d lxi h,prmpt2 , hdlog endif endif if dn eq mworder ;Generate the HDDMA's message if st506 ne 0 msprnt 'HDDMA + M5', maxmw, mwlog # map entry consists of 9 bytes: * * Logical drive number (1 byte) * * Track number of bad sector (2 bytes) * * Sector n2,16 dn set dn+1 endm endif if maxmw ne 0 if mwpart ne 0 ;Use non-standard partitioning tracks set mwtrks/mwlog ,256,0 dn set dn+1 endif if m10 ne 0 alloc hd,%dn,159,0 dn set dn+1 alloc hd,%dn,161,0 dn set dn+1 endif if m************************************************************************* * * * Morrow Designs IBIOS for CP/M Version ******************************************** if maxhd ne 0 if hdpart ne 0 ;Use non-standard partitioning tracks set hdks/4 if blocks gt 256 ;Use the remainder blocks set blocks-1 alv set (blocks/8)+1 alloc mw,%dn,%alv,0 dn set dn+1 enumber of bad sector (2 bytes) * * Track number of alternate sector (2 bytes) * * Sector number of alternate sector (2 bytes;Number of tracks per partition dsm set mwsectp/8*tracks/4-1 ;Number of groups per partition alv set (dsm/8)+1 dn set 0 r20 ne 0 alloc hd,%dn,255,0 dn set dn+1 alloc hd,%dn,255,0 dn set dn+1 alloc hd,%dn,129,0 dn set dn+1 endif endm e2.2. * * Copyright (c) 1982, Morrow Designs * * * * This CBIOS has been reconfigured so that it can run in thetrks/hdlog ;Number of tracks per partition dsm set hdsectp/8*tracks/4-1 ;Number of groups per partition alv set (dsm/8)+1 dif endm endif endif db 0 ;Force a complete hex file end ) * * * ***************************************************************** badmap: ds badsiz*9+1 ;32 entries + end ept maxmw*mwlog ;Generate CKS and ALV tables alloc mw,%dn,%alv,0 dn set dn+1 endm else ;Use standard partitioning ndif endif if maxfd ne 0 dn set 0 rept maxfd alloc fd,%dn,75,64 dn set dn+1 endm endif if maxdm ne 0 dn * * INSTALL environment. Generally this means that all the console * * drivers, list drivers, and the warm boot code in thedn set 0 rept maxhd*hdlog ;Generate CKS and ALV tables alloc hd,%dn,%alv,0 dn set dn+1 endm else ;Standard partitmarker dirbuf: ds 128 ;Directory buffer tempb: ds 16 ;A little temporary buffer *********************************** dn set 0 trkoff set 8192/(mwsecpt/8)+1 psize set trkoff*(mwsecpt/8) rept maxmw blocks set mwsecpt/8*mwtrks rept b set 0 rept maxdm alloc dm,%dn,75,64 dn set dn+1 endm endif if maxmf ne 0 dn set 0 rept maxmf alloc mf,%dn,2 disk drivers * * has been removed. Also, system dependant code has been modified. * * (system dependant code is code that usioning dn set 0 rept maxhd if m26 ne 0 alloc hd,%dn,252,0 dn set dn+1 alloc hd,%dn,252,0 dn set dn+1 alloc hd,%dn****************************** * * * Allocation and checked directory table area * * * *********************locks/8192 ;Generate some 8 megabyte ALV's alloc mw,%dn,256,0 blocks set blocks-psize dn set dn+1 endm blocks set bloc$ es memory locations below * * the IBIOS or code that directly affects the placement of various * * code modules in memory) es to say M5, M10, ... * * 9 27 82 Marc Redefined the dparam table structure * * 9 22 82 Marc Added a serial console for  10 82 Marc Public release of revision E.31 * * 11 9 82 Marc Reduced bad map size to 1 for non MW systems * * 10 18 82 Maration table * * 8 11 82 Marc Added DJDMA drive parameter table * * 8 9 82 Marc Added clock switching to HDCA code * The logical order of the disks can be set to any order. * * * * Disk systems: * * HDC3 10, 20 and 26 megabyte  Marc mwreset now sets *step and *dir for CMI * * 8 20 82 Marc Added 'equ'ed handshaking to the serial LST: * * 8 19 82 M * * * * Note: One important execption. The DJDMA drivers use addresses * * 50h to 5Bh for command channel informathe Switchboard * * 9 22 82 Marc Added initialization code for serial group 2 * * 9 22 82 Marc Added sector size byte to trc Fixed SETHIGH for 2 sided DJDMA 8 inch disks * **10 1 82 Marc Public release of revision E.3 * * 9 29 82 Marc 40H no* 8 9 82 Marc Added seek complete clearing in HDCA * * 8 6 82 Marc Added buffer disable on home * * 8 6 82 Marc Fihard disks. * * HDDMA 5, 10, 16, megabyte hard disk systems. * * DJDMA floppy disk controller with 8 and 5 1/4 inch disksarc Removed clock switching code from HDCA driver * * 8 18 82 Marc Added handshake configuration code * * 8 18 82 Marc Ation. This area is * * 'reserved' (and not used) by CP/M. * * * * Another note: The IBIOS's cold boot jump is nhe hdca DPB's * * 9 22 82 Marc Added sector size parameter to DPBGEN * * 9 9 82 Marc Fixed system length checks for 64K w points to the HDDMA command channel * * 9 28 82 Marc MW's now have 1024 directory entries * * 9 28 82 Marc Deleted the xed 8250 UART initialization sequence * * 8 6 82 Marc Strip parity on conout to clear up glitches * * 8 6 82 Marc Fixed. * * DJ 2D/B floppy disk controller with 8 inch disks. * * * * Written by Les Kent and Marc Kupper 3/4/82 * *dded handshake configuration bytes * * 8 18 82 Marc Removed 'equ'ed handshaking from LST: * * 8 12 82 Marc Added configuow a pointer to the * * HDDMA command channel. This pointer was formerly at 40h to 42h. * * * * This IBIOS can be cosystems * * 9 9 82 Marc SETHIGH was botching 2 sided DPB pointers * * 8 31 82 Marc Changed TRACKS in HD driver to HDTRAK Centronics drivers * * 9 27 82 Marc Changed login message to look like a label * * 9 27 82 Marc Changed the login messag the 8 inch dpb256ss DPB's EXM * * 8 6 82 Marc Increased the HD capacities slightly * * 8 6 82 Marc Deleted all non-su * * Date Programmer Description * * * * 12 30 82 Marc Fixed bad map error return in GETBAD * **11ration entries for a0 & d0 * * 8 11 82 Marc Added the autostart command structure * * 8 11 82 Marc Redefined the configunfigured to run with the following devices. * * The disks may be configured to run with any or all of the disk * * systems.  * * 8 27 82 Marc Added code/system length checker * * 8 27 82 Marc mwreset save/restores the track number * * 8 26 82% pported MW drives * * 8 6 82 Marc Deleted call to flush in conout * * 8 6 82 Marc Moved printer back to port 3 * * * * 4 1 82 Marc Fixed LISTST for PROM driver * * 3 16 82 Marc Added Tandon TM602 and TM603 drives * * 3 16 82 Marc  overlap * * 4 20 82 Marc Started testing and debugging of E.3 * * 4 19 82 Marc Added 1 sector to HD warm boot loader ;Set to number of HDC3 hard disk drives maxmw equ 1 ;Set to number of HDDMA hard disks maxfd equ 0 ;Set to number of 2D/B fl50-52 to MW driver * * 6 17 82 Marc Fixed Centronics drivers * * 6 7 82 Marc Fixed allocation map sizes * * 6 7 822 - March 4, 1982' revnum equ 53 ;IBIOS revision number 5.x = E.x cpmrev equ 22 ;CP/M revision number 2.2 ************* 7 28 82 Marc Moved conin flush call to conout * * 7 27 82 Marc Fixed double sided head settle time * * 7 14 82 Marc O Use 'part number' equates for MW drives * * 3 15 82 Marc Dropped hdrev and mwrev equates * * 3 15 82 Marc Seagate ST50* * 4 19 82 Marc Added mod. number to IBIOS rev. number * * 4 19 82 Marc Clean up login message 'if's * * 4 15 82 Maroppies maxdm equ 0 ;Set to number of DJ DMA floppies 8 inch maxmf equ 0 ;Set to number of DJ DMA floppies 5 1/4 inch hdor Marc Fixed MW partitioning * * 6 7 82 Marc Fixed HD partitioning (again) * * 5 13 82 Marc Fixed illegal MAC labels************************************************************ * * * The following equates set up the disk systems to beptimized MWissue * * 7 14 82 Marc Clean up login message for HD a bit * * 6 30 82 Marc Fixed MF multi density problems6 head settle is 0 ms. * * 3 15 82 Marc Added MiniScribe 1006 and 1012 drives * * *3 1 82 Marc Public release of revisioc Fixed MCR Initialization for LST: * * 4 15 82 Marc Added Seagate ST412 drive * * 4 6 82 Marc Moved serial LST: devider equ 0 ;Set the order of logical drives ELSE 0 if mworder equ 1 ; not included. fdorder equ 0 dmorder equ 0 mforder equ * * 5 11 82 Marc Fixed North Star drive configurations * * 4 30 82 Marc Fixed Quantum Q2040 tracks to 512 * * 4 29  included * * along with the types of drives and the logical order of the * * drives. * * * *************** * * 6 29 82 Marc Added Olivetti HD561/1 HD561/2 drives * * 6 28 82 Marc Added a MW error reporter * * 6 18 82 Marcn E.2 * * 2 -- 82 Marc Pre-release testing and debugging * * 2 1 82 Les + Marc Initial coding of revision E * * ce to port 2 * * 4 1 82 Marc Added common group select routines * * 4 1 82 Marc Fixed Diablo HyType II initialization  0 ;HDC3 controller disk drives. Set only one m10f equ 0 ;Fujitsu M2301B m20 equ 0 ;Fujitsu M2302B m26 equ 0 ;Shugart82 Marc Fixed ST412 step constant to 0 * * 4 26 82 Marc Added unallocated writing * * 4 22 82 Marc Fixed HD partition********************************************************** numprd equ 5 ;Number of disks products supported maxhd equ 0  Added nonstandard system mode flag * * 6 17 82 Marc Added a buffer error flag * * 6 17 82 Marc Added save/restore of  * ************************************************************************* title 'IBIOS Revision E for CP/M Version 2.&  SA4000 m10m equ 0 ;Memorex ;HDDMA controller disk drives. Set only one st506 equ 0 ;Seagate ST-506 st412 equ 0 ;Se badsiz equ 1 ;No badmap if no MW drives endif m10 equ m10f or m10m if hdpart ne 0 ;Use non standard partitions hdl * * * ************************************************************************* hdpart equ 0 ;Set to number o****************** retries equ 10 ;Max retries on disk i/o before error clear equ 'Z'-64 ;Clear screen on an ADM 3 anul* Another way the drives are partitioned is the so called 'even * * partition' formula. This means that the drive is split indm+maxmf if maxlog gt 16 ;Test for too many drives 'Fatal error, more that 16 drives specified.' end endif cdisk eqagate ST-412 cm5619 equ 1 ;CMI CM-5619 ************************************************************************* * og equ hdpart else hdlog equ m10*2+m20*3+m26*3 ;Logical disks per drive for HDC3 endif if mwpart ne 0 ;Use non standarf non standard partitions mwpart equ 0 ;Set to number of non standard partitions ****************************************** equ 0 ;Null aetx equ 'C'-64 ;ETX character aack equ 'F'-64 ;ACK character abel equ 'G'-64 ;Bell abs equ 'H'-64 ;Back Sto * * equale sized partitions with the only restriction being that no * * partition be over 8 megabytes in length. * * u 4 ;Address of last logged disk bdos equ 5 ;BDOS entry point buff equ 80h ;Default buffer address cpmout equ 2 ;BDOS's * * Since most hard disk drives hold more than 8 megabytes we * * partition the drive. We partition our drives using two did partitions mwlog equ mwpart else mwlog set st506+st412*2++cm5619*2 ;Logical disks per drive for HDDMA endif hdc3 equ ******************************* * * * The following equates are internal to the IBIOS. * * * *************pace aht equ 'I'-64 ;Horizontal tab alf equ 'J'-64 ;Line feed avt equ 'K'-64 ;Vertical tab aff equ 'L'-64 ;Form Feed ac * * All hard disk drives shipped from Morrow Designs are partitioned * * using the standard partition formula. If the  console output routine ************************************************************************* * * * The followifferent * * formulas. * * * * One is the so called 'standard partitioning' where we try to * * create as manm26 or m20 or m10 ;HDC3 controller fujitsu equ m20 or m10f hdspt equ 32*m26+21*m20+21*m10 ;Sectors per track hdma set st************************************************************ if maxmw ne 0 badsiz equ 32 ;Number of badmap entries else r equ 'M'-64 ;Carriage return xon equ 'Q'-64 ;Xon character xoff equ 'S'-64 ;Xoff character aesc equ 1bh ;Escape characteuser wishes to * * implement even partitioning then he/she must set HDPART or MWPART * * to the number of partitions desired.ng are internal IBIOS equates. Most are misc. constants. * * * *******************************************************y 8 megabyte partitions as possible plus a small * * partition to take up the slack on the end of the drive. * * * 506 or st412 or cm5619 ;HD DMA controller mwspt equ 9 ;Sectors per track maxlog equ (maxhd*hdlog)+(maxmw*mwlog)+maxfd+max' r ars equ 1eh ;RS character aus equ 1fh ;US character asp equ ' ' ;Space adel equ 7fh ;Delete ***********************H d$sel2 equ 3 ;Drive select d$home equ 4 ;Home drive d$strk equ 5 ;Set track d$ssec equ 6 ;Set sector d$sdma equ 7 ;Set DMnum eq mworder dw mwdst endif if num eq fdorder dw fddst endif if num eq dmorder dw dmdst endif if num e Ä!~w#~w\!D!!"N#FD !4!! N#FD !>w#w!~#~ !!~#fo 6!~w#~wPog equ $ dw 0 dw 0,0,0 dw dirbuf dw &dpb1&dpb2 dw csv&nam&log dw alv&nam&log endm alloc macro nam,log,al,cs csʽ!~#~ʽ@ ý!!!!~w#~w+~#foN#F(!~w#~w!~w#~w!~w#~wñ!!$!~************************************************** * * * The following are the macros used in generating the DPH, DPB *0F!9N#F#^#V#~#fo"Xkb"Xi`"XOGposLoad size is %h hex bytes longOutput file is %p Addresses don't q mforder dw mfdst endif endm ************************************************************************* * * *!!!N#FzEy x«!; !!!!"N#F]yx!T!!! N#F]yx!v&nam&log: ds cs alv&nam&log: ds al endm ************************************************************************* * w#~w+~#foN#F !>w#wF!~#fo~OG!; F!!!D!~#foN#F !~#~!!!4!~and * * allocation tables. * * * ************************************************************************* matchSizes don't matchUnexpected last line in %pCan't make room for headerCan't create '%p'prlhx1hx1hx0Bad option -%ac The folloing are offset numbers of Device Specification Tables. * * * ***********************************************4!; ! ~w#~w!~w#~w!#X##N#F+++N#F!N#Fr! N#F!!N#F!N#F!N#F!N#Fͣ! 9!" * * The following marco is used in generating the logical order of the * * CP/M drives. * * * ***********#foN#F 3!!!4!~#fo##N#F !~A#~ʄ!!~#fo~#fo~!~#fo~!~#fo~.!~#fo6dpbgen macro nam,log,dspt,dbsh,dblm,dexm,ddsm,ddrm,dal0,dal1,dcks,doff,ssiz dpb&nam&log equ $ dw dspt db dbsh db dblm dprlMAKEPRL Version %i.%i gV!9!>w#w!>w#w!>w#w! >w#w!>w#w!>w#w!>w#w!~w#~w!************************** d$wboot equ 0 ;Warm boot d$stran equ 1 ;Sector translation d$sel1 equ 2 ;Drive select, Return DPN#F=! N#F=!N#F=!$!]!~#fo!yOx#G!>!!FnV!!  #!; !************************************************************** order macro num if num eq hdorder dw hddst endif if \!"!Dywx#w! !4ywx#w!!!!$$ywx#w+~#~!$!; !!$!~#foN#Fb dexm dw ddsm dw ddrm db dal0 db dal1 dw dcks dw doff db ssiz endm dphgen macro nam,log,dpb1,dpb2 dph&nam&l~w#~w!N#F!N#F!!~#±@ !~#fo~#fo~-!!~#fo~#~!~w#~w+~#fo~OG!2[U!~#~( ~#fo!yOx#Gyx(!p; !>w#w!!  #!!~#fo!~#fo }o|g}|!>w>#w!N#F!!!!^ ywx#w+~¬ #~ !N#F! ; !~ #~ !N#F! ; !!  # !N#Fo ~0 !~#fo ~0ʣ nV!!N#F!!~#fo#(y x nV!!N#F!!~#fo###(y x't write out seg %igV!9!\~#_!>w#w!~#~!/X!~#fo 6!~w#~w0!!~#fo}o|g!QP}C !N#F!~w#~w6.!~#fo~, !N#F!~w#~w!N#F!~w#~w~Û !N#F!~w#~w!N#F!~~w#~w6!N#F!~w#~w!~#fo!yOx#GyOxGyw!N#F!~w#~w!~#fo!yOx#G!8Q}o|!~w#~wᗕ>!!~#fo||g}o}|x!!~#fo!~#fo !8Q}|!~#fo)!T ~#fo!~#fo)!! ; !!'X##N#F+++N#F!N#F̈́)xB!N#F! ; nVBad line in hex filegV!9!!N#F9 y€x nV!>w#w!!~#fo  #~ !!~#fo)! ~#fo !!~#fo) !~#fo (yu xʣ nV!|!!~#fo}o|g}|!!/\ ° #=*/\! ##N#F+++N#F!N#FZyxr*/\!; r!>w#w!w#~w~ !~#fo6! ~& #~ʃ nV!~#fo6nVgV!!N#F!~w#~w!N#F80yʎ !~#fo ~ ” !~#g}!N#F!~w#~w6!N#F!~w#~w! ~#fo}o|g}!N#F!~w#~w! N#F!8Q}o|g}!! yOx#Gyx3!!~#fo ! V!!~#fo !~#fo}/o|/g ! !  #y! !~#~!!‰nV!! N#F!N#F!N#F!^ ywx#w+~#~!H; !~#~nVnVCan't open '%p'gV~#fo#~0³ !~#fo##~0³ nV!~w#~w nVCan't rewind '%p'file '%p' not at correct start addressUnexpected las~ր#~0!~#fo)1\ >w#w!~w#~w>2\2\_!/X!~#fo !~!:\:\#!!~#fo"\!!~#fo)1\ ~fo 6nVnV!~#fo ~ < !~w#~w< Error: gV! ! N#F!N#F!N#F!N#F!!F~#fo!yOx#G! ||} !!+X##N#F+++N#F!N#F̈́)xT!; !!!N#FzEytx!~; !~#fo!~#fo  !!~#fo!~#fo }|!X##N#F+++N#F!N#F!~#fo)! N#F!~#fo!~#fo !!!!!N#F͐ywx#w+~.#~E!N#F!; nV!~#foMDnVCan't write out bitmapSeek error in wrheadCat line in hex file '%p'File '%p' not in hex formatCan't read '%p'gV!9!!N#F9 yg x{ !N#F!4 ; !#!N#F! ##N#F+++N#F!N#F'y¶x!N#F!; !~#fo"/\*/\)1\ >w#w=!>w#w!~#~nVUsage: makeprl [-s hex-no] [-o output] hex-file1 [hex-file2]gV! !!FnVgV!~#fo~:y nV!~#f!##N#F+++N#F!N#F̈́)x!i; !N#F! N#F!N#FzEyx!R; nVCan't read in seg %iCan 9!~w#~w3gV!~#fo~ʃ !~#fo~. ! ~@ #~ !~#fo~ !N#F!~w#~w!N#F!~w#~w~n't write headerCan't rewind filegV!9!>w#w!~#~!!~#fo 6!~w#~wö!!}|!N#F!) !/X!~#fo 6!~w#~wnVgV!!##N#F+++N#F! N#F!N#F͍! 9nVgV!!##N#F+++N#F! N#F!N#*``>Z*``~OG! MDä*``~OGyw!~w#~w*``#"``C!tN#F!t~w#~w6e!v!N#FP*b`#"b`ò*b`~>V|:``2``:a`2a`*d`#"d`Ñ*d`~A*d`>Z!*d`~A*d`>Z*d`~OG! MD*d`~OG! }|!!   #X*N#F! ~w#~w~#fo}|!~#U!!!  #H!N#FO!N#Fywx#w!~#ʟ#!!  ##!!!Nd`> *d`~!``>#*d`~-n!>w#w*d`#"d`:``2``:a`2a`:``2``:a`2a`*d`#"d`s! ~#~‘:``:a``*d`"b`*b`~/*b`~%/*b`#"b`*b` "d`!b`:d`:e`#h*b`!d`yOx#G*d`!N#F!~#fomV*b`*b`#"b`~|P!F͍! 9nVgV!9!!N#F!͖Qx2P`2Q`x2S`y2R`!P`!Q~#~#~#~!!##N#F+++N#F!N#F̈́)x!=!!*b` $y(x~!!*b` !!! 9!F~!N#F!~w#~w)!v :b`w:c`#w*bd`!yOx#GP can't write can't read O!9!t!}|!"``!*``*``#"``~!>#!>#*#F!~#fomV!~w#~w_*b`~p# !! ~#fo~#~!! N#F! ~w#~wN#FL)ywx#w!~#U!!!ڑ*d`~0‘*d` ~A;*d` >Z;*d` ~OG! MDG*d` ~OGyxPx‘*d`##"d`:``2``:a`2a`Ñ*d`~+*d`#"d`:`>w#w!6 *b`~-½!>w#w!*b`#"b`*b`~*b`#"b`*b`~+!*b`#"b`*b`~*b`#"b`! !*b`;i`"b`!>wnV! >w#w+~#1!!/X!N#FzEnV!!/X!N#F80nVCan't write out memoryFlush can't seekgV!9!*`~*b`#"b`~gV!N#F!~#ʫî!N#F͛9nVgV!N#F!\c,nVgV!!N#F!\!#.nVO!``> ,*``~,!>w#w!v/ywx#w!"b`!t:b`:c`#*b`~<!=!!*b` ͐y~!!!*b`   # !N#F !N#Fywx#wU*b`~l› !~a!!! ~#fo~#~#~#~!>w#w!~w#~w+#~n!!!~#fo`2``:a`2a`!``>#*d`~0C*d`>9C!*d`~OG! }|X*b`!~#!N#F>O>G!N#Fywx#w!``>##w*b`~.)! !*b` ;i`"b`*b`~aM*b`~hM*b`~oM*b`~ux!*b`*b`#"b`~!~h>2``2a`õ!6a/\!͖Qx2P`2Q`x2S`y2R`!P`!Q~#~#~#~*\#"\!!##N#F+++N#F!N#F̈́)x!a; *\}o|g!/X"d`*d`~#8*d`N#FL)*d`N#F!N#FzE*d`##"d`PO!~#fo"d`!~#fo"``!~#fo"b`*d`~nq*d`~N¢*d`#"d`*``*b`N!#!! 9!F~!>#CÔ!~w#~w*``#"``r!>#*``> *``~!tN#F!t~w#~w*``~A !##~!!$T] *b`~f¢!!!}|!!N#F!!yOx#G! ~#fo >+F+N= !&!9ywx#w! *d`~A%*d`>Z%*d`~OG! MD-*d`~OGyl6x*d`#"d`*d`~a*d`>zÝ!!N#F! N#F͖Q!~#fo }!~o˜>2``2a`õ!~u¯> 2``2a`õ!"``*b`~x!>w#wU*b`~b¡!! N#F! ~w#~w~#~!! !N#FzEyx"!J; nVO!~#fo"d`!~#fo"``!~#fo"b`!>w#w!:d`w:e`#w!>w#w!``>#ґ*#F*b`~w#~w~#fo}|*d`MDP*``>w#w*d`~0*d`>9*``*d`~OG*``~#foMD)) )  }|*d`#"d`ìO!9!~#fo"d* ! ~#fo }|U!!}|!*``! ~#fo##N#F+++N#F!ͮ*ywx#w! ! ~#fo####}|U!!}|! }|!>>#'!>w#w!!N#F!!<~w#~w!!  #(!~#fo!yOx#G*`` "``!!~##~w6%!>#&*d`*d`#"d`6.>2b`2c`!:b`:c`#E&*``*b` !yx#E&*d`*d`#"d`!*`` ~*``#"``*b`#"b`í2[`2Y`2X`!X`Q##~*``>9',*``~'w*``!d`yOx#GPwrite error write error bad putc call O!~#fo"d`!~#fo"``!d`~U*b`~iU:b`2b`:c`2c`U!>##!N#F!N#F!N#F!~#fomV!~#"!!  #"!!!N#F !Qá*>2d`2e`!*d`*b`fJxT*!*`` ~*d`}ƀo|g"d`**``$ *d`!~#fo MDx2P`2Q`x2S`y2R`!P>w#w! ! ~#fo####}|U*b`~d#"!!}|!!>>#!!!N#F!! ~#fo >+F+N=!!>$!~!>#;(*b`*b`#"b`60!d`>#(*b`*b`#"b`6.×(!>#(*b`*b`#"b`*``!yOxGyxҁ(*``*``#"``~OGÄ%*d`*d`#"d`6e!#~m&*d`*d`#"d`6-!!~#fo>o>g}|{&!:b`:c`#&*d`*d`#"d`60*b`#"b`E&*d`*d`#"d`6+*d`*#Ÿ,!!T,!zE!F:a`,*d` ~#~,*d` N#F*d` ~w#~w*d` :``wg-*d` >#-*``MDP*d`!~#fomV!~w#~w#gV!N#F!!N#F͛9nVO!9!~#fo"d`!!F`;K$!!P`~#~s$!P``!S!Q~#~#~#~!~#foMDPO!~#fo"d`*d`"``!#~+! >#+!!P`~#~#~#~!P`͕T9ywx#w! ! ~#fo }|U*b`~cG"*b`~sG"*b`~iG"!~ʉ"!~a¤"!! N#F! ~w#~w}|*b`~c"!>(0yw!~w#~w;(!#~(!d`>#(*b`*b`#"b`60!~w#~w:d`2d`:e`2e`×(!d`>#9)*b`*b`#"b`*``!yOd`#"d`!N#F! QP0 }*d`*d`#"d`!N#F! ͘P0 }*d`!yOx#GPO!9!~#fo"d`!~#fo"b`!!F`;K N#F*d` *d`N#FzE*d` y.-x#N-! !G,!zE!Fg-*d` >w#w*d` :``w:`` t-:a`‹-*d` ~NO*d`*d`#"d`6-!!~#fo!~#fo }|!>>#$!>w#w!!~#fo#! >+F+N=$!94! 9ywx~#~#~#~*``*``#"``6-! ~#4+! > w#wY+! #~Y+! ! ~#fo>o>g}|!! #~~+~ !#~+!w#wq#!:b`w:c`#w!>w#wU!! N#F! ~w#~w~#~*b`~c@#!``>#@#!~w#~w@#!!~#fo~#~!xGyx )*``*``#"``~OG#)0yw:d`2d`:e`2e`(*b`!yOx#GPO!~#fo"d`*d`"``*``~r)*``#"```)*``!d`yOx#8'*b`*b`#"b`6-!!P`~#~$'!P`NO!"``!!! >+F+N=R'*``94! 9ywx#w!!~#fo*d`ˆ-#~,*``MDP*d` N#F*d` *d`N#FzE*d` y-x#-! !:,!zE!FP*d` >w#w*``MDPwrite #w!!N#F!~#fo#!<~w#~w>2``2a`!:``:a`#%!:``:a`#҈%*d`*d`#"d`!*`` ~*``#"``!~w!R+! N#F!P`~#~#~#~!P`!ͨS##N#F+++N#F*``ͮ**`` "``*``!P`~#~#~#~!P`!S>02Z`!N#F!8Q}!!~!!}|!>w#wq#!!}|!*``!N#F!3ywx#w*b`~cU*b`~sGPO!N#FʹFi`"b`!b`~#ʮ)*b` ~)P*b` ~#fo"``! ~#)*``$ !~#~#~#~á*! ~)#~**``$+ error write error bad putl call O!~#fo"d`!~#fo"``!d`~#c.!!.!zE!FP!~#fo"b`!b`>#/!*NO!!`;K5*N` "b`!b`>#5!*b`)))` ;K6!!P`~#~4!P`*b`)))` @LO*``!*b`d`! 5*d`" ~w#~w*d`$ >2P`2Q`>2S`>2R`!P`Q+2*``~OG!$0[U*``!yOx#GP222*b` ~OGy2x3c`*``~g9:b`:c`g9*b`*b`#"b`*d` *``~aR9*``>zR9*``~OG! MDZ9*``~OGyw*``#"``9:b`:c`9*b`*b`#"b`0*b` ~0*b` ~OG! 0[U*``!yOx#GP!*b`VG!0[U!d`~#0P*d`! ~P1*d`* 6}*d`* ! ! !b`6*``MDPPONMLKJIHGFEDCBACONRDRPUNLSTO>2d`2e`!"_:d`:e`#k7*d`=*d`#"d`J7:^OG! *^Md` *d` ~#fo }|!b`>#/*d` ~#~/!N#F!~w#~w*``*``#"``~:b`2b`:c`2c`*d` ~w#~wÛ Q "``6>2b`2c`!:b`:c`#6!~#6!!P`~#~H5!P`!`ͦMO!!ͭO!!P`~!F*``#"``!~w#~w2O!~#fo"d`*d`"b`!#~s3!>#s3!!~#fo>o>g}|*b`*b`#"b`6-!~#fo}o|*d` 6 g9*``~OGPO!9!~#fo"d`:^9!! y2^!>w#w!!"_  #9!~#fo))_ ~:!!"_ *d`! *d`+ ~OGyw*d`" *d`, }|*d`" ~#fo*d`+ ~OG 6 *``*d`" N#F*d`" ~w#~w~*d`! 5*b`~ODPO!~#fo"d`!^ywx#w!~#fo~#7*d`"b`!~#fo~#fo"``*b`*`` 7*``~7*b`#"b`*``#"``7P!~w#~wß7*b.*d` ~/#~/*d` ~#/*d` ~#fo*d` ~ /*d` N#F*d` *d`N#FzE*d` yo/x#/! !-!z#~5!P`!X`!N#F UNO*d`*d`#"d`!~#fo0 }*b`#"b`5!!`;K!6!!P`~#~5!P`!`@Lg"``!~#ž3!> w#w3!#~3!!~#fo>o>g}|!:``:a`#3!N#F*``!N#FP*b`3*b` "b`*b`*  #:P!~w#~w9!!~#fo))_ }|!~#fo6!!~#X:!~#fo~w!~#fo##>w#w!:d`w:e`#w>2``2a`GyOxGy1*``#"``!~w#~wt0*``!! yw{1P*``~ t0*``~t0*``~ʟ0*``~ 1*``!yOx#GP*``#"`*`` 7!~#fo##~OGPO!~#fo"d`!~#fo"``>2b`2c`*``~.ʮ8*``~ʮ8:b`:c`8*b`*b`#"b`*d` *``~a8*E!F/!b`>#n.!*d` *d`N#FzEy½/x/! !.!zE!Fn.*d` >w#wn.!~#foMDP*d`O*``#"``5:b`2b`:c`2c`à4!P`~#~/6!P`!`ͦM!`;K5*N` "b`!b`>#5!*b`)))` P`~#~``!N#FP0 }*b`>9&4*b`~'w*b`!d`yOx#GPO!9!~#fo"d`>2``2a`!#~4!!P`~#~s4!P`*d`~::*d`~::``:a`;*``*``#"``! *d`~a:*d`>z:*d`~OG! MD:*d`~OGyw;!*`` 6*d`~:;!~#``!~w#~wt0P*``!yOx#GP!>#t0*d`! ~t0*``*d`" ~#fo~*b`~OGyOxGy¾2*``#"``!~w#~w*``>z8*``~OG! MDá8*``~OGyw*``#"``@8:b`:c`8*b`*b`#"b`*d` 6 î8*``~.8*``#"``8*``~8P>2b`2 >w#w/10122+222 223O!N#FʹFi`"b`!b`~#[0P*b` ~#fo"d`!~#fo"``!>#|6!P`!ͦMO!`;K6!!O!*b` Q:``2``:a`2a`:b`2b`:c`2c`W6!:b`:c`#7*d`*d`#"d`60*b`#", fo"d`!~#fo#:^wT;*d`#"d`À:!~#fo#!̈́7yw~M;!N#F=P*d`#"d`!~#fo#~;!~#fo#~OGyy;x;!ŽA!~#fo"_!~#fo!~#fo :_:_A!~#fo!~#fo "_!!~#fo##A@bad free call O!~#fo "d`!t of heap space O!N#F!N#F?i`"d`!d`~#ʿ?*d`MDP!!~?!zE!FPO!~#fo"d`:d`:e`?@*-F*d`#"d`!~w#~wE*d`!yOx#GP*d`!``yOx#G*``*b`ͦC*d`!``yOx#G}cF|lFP!>#E!!wEP:a`=*d`61!~#fo"``!``>#=*d`*`` 60:``2``:a`2a`Ý=*d`*`` 4Æ=PO!N#FʹFi`"d`!d`~#=P**b`!yOx#GP*d` ~1D*d` ~OG!C[U*d` ~#fo"``!*d`VGyUDx¾DP*b`~OG! !~w#~w*b`~Š;#~;!!͑?i`"b`!~#fo##:b`w:c`#w!*b`|K*b`( >w>#w!~#fo#~;!~#foMDP!~#foMDP*d`*b`8~#>B!_:d`:e`#$B!_:d`:e`#KB!!A!zE!F!~#foMDP!_~#kB*d` >w#w*d`"_>B!_:d`:e`#қB*d`d`MDi`#}o|g##"d`!_"``*``~#fo"b`!b`~#k@*b`~#fo####!d`yx#ڍ@*b`!d`  #Қ@*``*b` ~#~ñ@:_x@:_@:_*b`ͦCy”FxʝFP*d`#"d`!~w#~wEO!~#fo"d`:e`F!"_:d`:e`#F*d`))_ ~FP*d`))_ MDPgV!_d` ~#ʌ>*d`~OGyOxGyŒ>!*d`RI*d`~OGy OxGyj>*d` ~#fo ~w*d` N#F! *d` !*d` N#F#"b`ÿC*b`~OG! pD*b`~OG! pD!~#foMDP!>#?E*``! ~?E*``" N#F*``" ~w#~w*b`*b`#"b`yB*_"``*`` ~#fo"b`!b`~#B!d`:b`:c`#B*b`"``áB!b`~# C*d` :b`w:c`#w*`` :d`w:e`#w*d`?2_:_2_@*b` "``@*``*d`*b`͞>ywx#w*b` !~#~*b` MDP!>w#w!d`:_:_#$A!!:_w:_#w+N#F~#%G!.G:_G:_%G*_mVi`"_F* _mV%GO*_"d`!~#fo"_*d`MDP8I2IIIO!~#fo"d`*d` ~#fo"``!*``$ Aywx#w*d`6!~#foMDPO!~#fo"d`!~#fo"``*d`*`` "b`*b`*d`~#fo!``yOx#Gywx#w*b` *d` ~#~*d`*``~*``$ >2P`2Q`>2S`>2R`!P`Q!~w#~w*``! 5þD*d`~OGyOxGymE*``! ~mE*``" ~#fo6*d`~wÿC O!~Œ<#~¨B*d` >w#w*`` :d`w:e`#w*``?>BgV!:_w:_#w*_!~#fo "_!:_:_xC!f`:_:_҉C!~#fo5Cywx#w+~#$A:_2_:_2_@!~#OA!!:d`w:e`#w+N#F5Cywx#w!~#_AP!~#fo!~#fo }|!_~#P`~#~#~#~!P`!$T##~#~*``$ ##N#Fi`}o|g"b`*``! !!b`yOx#Gyw*``" *``* *b` }|!~#H }|*b`MDPO!~#fo"d`*d` ~#fo"``*d`*d`~#fo ####!``yK?x#{?*d`*``~#fo####  *d` *`` ~#~PouN#FʹFi`"b`!b`~#EP*b`~OGyOxGyE!N#F!N#F*b`ͦCP!~#fo"d`!>#F*d`"``!>#-F*d`~ ~#fo"d`!#~=!!  #=*d`!~#fo ~5=!~#fo "``:a`=*d`*`` ~9=*d`*`` 60:``2``:a`2a`J="_nV!~#foMDnVDD^DDO!~#fo"d`!~#fo"b`!>#D! yOxGyD! yCxD!FD- !*``( H #HP!*d`RIxPH!N#F!N#F*d`fJxVHP*`` ~OG*`` ~OGyOxG}|HN#F!rV!~ʨN!~#ʨN~w! N#F !#~·NW!9~#fo~#N~ƀw!9!9!N#F ! #wNàM!~L!>#w›L!4!q#p! N#F L!4 !]WyʠMy!Ox#Gyƀ+wx#w !#w L!69!~#~#~ #~{S>#># >#͹R!9MD!9~#foR! 9MD!9~#foR2R!9N#F!9SR͹R!9MD!9~#fob`!N#F!8Q"``*b` ~OG:``¬J:a`J*d`~OGy OxGy[K*d` ~OG! *d`~OGyOxGyK*b`! xN#FP! 9q#pW!9~$Q/G!9~#fo^#VzK_>WxƀGzƀWyoxL #W!9N#F!9~#fo ## # +++ #W!9MD!9~#~#~#~ !9~w#~w#~w#~w#~w#~w#~w#~w!9MDʮI!*``( N#F*d`fJy¥IxIP!~#`J*d`~OGyOxGy`J*d` ~OG! *``! *d`~w`J*d``!"``"b`"d`!9~w#~w#~w#~w+MD!9 _ #P{ !94P! 9~iP+w>#w! 9N#Fx}PO>GP &%NN!~O#~Gyր+wx#w! #w )N>8!w! ~#+~w ?N!~hN!MD!  #^N!#~w oN!56N!+~w###~w+~w {TW!9~#fo##w>#w>+++w>#wMD!9!9!N#F!>w#w#w##w#w!!rV! N#F !#~ L>5L>5L! 9N#F!9~#fo# ##:L +:L LчWLL!9!9!6!N#F!]WyŠL! N#F > ! 9  # # #UR!9MD! 9  # # #!94UR!9!9W#~#~+++~#~#~R#>#>+++># ~OG! *``* ! *``! i`"b`!! !b`~#OJP*d`~w*d`~wîIPO!~#fo"d`*d` ~#fo"ҍPO>G! 9q#pW! 9~P+w>#w! 9N#FxPO>GPPO>G! 9q#pW! 9N#FP! 9q#pW! 9. TWͶTq#px#w#wTͶTq#p#w#wTͶT w #w #w #wTͶT w #w #w #wT~#gU#~#foy#{Ux#|U+++~#fo##[U@ BCG@M [u+p~ yW! ~#~WҚW+©W WW>w+~w}Wi`>#w¼WJ!9N#F###q#p+++q!9N#F#q#pcopyright (c) !9!9!N#F!]WyaV!q#p! N#F!]WyU!N#FKV!yOx#GUyV+~w#~w!UO>G! ~#+1979 by Whitesmiths, Ltd.975717-7+7)7'7%7#7!77777 7 7 ~wU Vw yVU!MD!  #w)V!N#F!rV!MD ! ~#fo+ #wXVW!9!9N#F! 3 Copyright (c) 1979, Digital Research????????????CON:RDR:PUN:LST:DEV:VAL:USR:DSK:TTY:CRT:BAT:UC1:TTY:PTR:UR1:UR2:TTY:PTP7 7 7 7f`.G~Vi`+ >#w‹VæV+¦VšV[W! ~V# +~w³V!9~w#~wæV! ~Vi`+ #~wV!9~w#~wV Wi`7#~:UP1:UP2:TTY:CRT:LPT:UL1:R/OR/WSYSDIRR/O R/W SYS DIR ** Aborted **Active User :Active Files: Drive Characteristics6 $_ wVæV!9~"Wi`+#wW[W5Wi`>#w+W>w! !9z~w+~ w++~ wOW!!9N#F!9^#V! #~#/ 5536: 128 Byte Record CapacityKilobyte Drive Capacity32 Byte Directory EntriesChecked Directory EntriesRecords/ ExtentRvO!w 6,]!v6>!v*v&w ~һ*vM !v4˜8AO͐:͐ͱ*##N!ͽ"* N#F*͠"!b/~,H~:H~*H~.H~>H~<H~=H*]& 6!]4T!]4!cq*a&Y :cw!a4͠Q" 8AO͐jͱͷDM͏ m  Z"l"!6>ʥ *}҆ *M ͱ*}x O͐} W͇͐ /ҋͺ *2!"q*"&L ͐ ͐ ͐!$p+q*#~*#N͐*##"#÷!&p+q͠*%DMͱ O O!(q*(&:2͠!4 F :® )!6>!ګ ͠:O!9 DMi 8ͱ!6> !ڤ Å :2ecords/ BlockSectors/ TrackReserved Tracks is Temp R/O Disk: d:=R/OSet Indicator: d:filename.typ $R/O $R/W $SYS $DIRDisk S>!H% - *DM ͱͷDM  ͱ* N#F 9ͱ * ^#V))DM Tͱ* ~fr*d*f!is*d́"dPY! "f>!h#~Haͫo!h6:i0O͐!mr+s+p+q*lͱ !+s#r!+s#r#4D ͠:\ʹ :\=Oͳͩ !6!)6l :) :)=2) :] & !"}2\!h6?!L!*p+q*)O2'!,p+q*+O2'O2'O!.p+q*-LRRLR\Lk ä  ͐:!O!Y DMi w !4C F :¿ >F : F :=229:Y= ;>9*&Y DMtatus : DSK: d:DSK:User Status : USR:Iobyte Assign: =Bad DelimiterInvalid AssignmentBad Delimiter: Bytes Remaining On DM oͱ*DM ͱ*N#F ͱ * N#F ͱ͠!p+q͠*DM':͐ͫZ"!6> *} *MTZs#r*lڶ*l+s#r*jN#F+q#pÌ!nq!"o"q}2uo&"s* s:n*sDM2u:uqosj6?\:'C:'ƀo&")!)6!"):)/)HҘ]!)6> !)ڎ*)&*)*)&*) y!)6 Ä:) R" O!/q*/& L!1p+q*0#L~*##N!ͽ͞"T!Vq*VMͳ!Xp+q!W* >Wr#MͲ!_ =2 I>!6:=28 :2:2 :!!29:Y T >:Y,e \>Ì !p+q*~:ʉ *N͐*R/, Space: Invalid File Indicator** Too Many Files **File Not Found Size Recs Bytes Ext Acc65536 set to R/O Invalid!+s#r#4 !s+p+q!6!66:!ڄ !6!6>!r *&**&Y i !6!4+4A :} :!*s"s*o͊O !v6>!vQ*v&w 6`i+46)A*:'ʓ:'O!) ~2vʍ:2):)<2)M*)#")/:)ҩ*)+")`*")#"]!*)!/H!")!"]*)) *)s#r!p+q!`6>!`6*`&*^*`&Y />!`4 >*]& ~ O!]49!a6:a*]& ~2bO>z*bM >#"o :͐!p+q!'"!6> **{2*́"PY! ">!+~H !6:0O͐à k͐ Disk AssignmentWrong CP/M Version (Requires 2.0)!9"2!T OË!]6:\:] Hr3 Ë:\ʀË4- >!699 2¨ :!4: :2!6+6>! :O!9 DMi ͱ:!O!Y DMi :20 )6> !).*)&*)*)&*) w:)<2)*)) >w#6*)) w#6*)!) w#6*)%) w#6*)) N#F*)) q#p*)%)-:YS:Z Hҧ!6> 2)½>!)6> !)*)&*)>2) :) .͐*)M͐:)<2)remain in the same order, the routines * * may be changed, but the function executed must be the same. * * * *******"))ҍ*)) ^#V")]͠.*)DM\ -°!\6:\ͣ:ͱ*}DM'ͫ*)%) N#F'ͫ*) *) ~e *) * ~o&͞ *)%) q#p!)6* >!)6!)6>!)=:)!)w=*)&*)~2):99:Y=/9&ͩ c,Hͩ 9 EHͺ i`N#Fog_og_ogD****************************************************************** bios equ $ ;Starting location jmp $ ;Cold boot entry!) N#F'k͐ͫ*)) N#FͫR͐/͐ *) ~IO͐NW͐ͫ8AO͐:͐ *) ~2)t(͐:)҃))*)& *):)2):):*)!) *)) s, >X\:)“>!d!")>!)d!"M!>))덑o|gҘ =†DM!>))ҭ =¥~ ³^#V) ½^#V|g}o _{ozgi`N#Fogo&og_{_z#W point owboot: jmp wboot ;Warm boot entry point jmp $ ;Console status routine jmp $ ;Console input ocout: jmp $ ;Conso͐*)#")Ã& \!"))\Ұ*)")]͠*)M! ^#V *) >*) w *) >*) w *) >*)A address d$read equ 8 ;Read a physical sector d$write equ 9 ;Write a physical sector d$bad equ 10 ;Return pointer to bad sec)!")*++!)a*)) ^#V")]*)")*)) ^#V")]!)6> !)T*)&*)~2)*)&*)~2)O;*)) ^#V"le output jmp $ ;List device output jmp $ ;Punch device output jmp $ ;Reader device input ohome: jmp home ;Home drive w *) >*) w.*)DM\ -+!\6uͱ:)O! DMͱ*)#")Ù*))))))"):m w>.Yn tor info ************************************************************************* * * * The jump table below must )*)) *)) N#Fq#p*)) *)s#r*)#")!)6 J:)!)J!)6 :)<2)*)")҈q:tw͠ͱ!1  osetdrv:jmp setdrv ;Select disk osettrk:jmp settrk ;Set track osetsec:jmp setsec ;Set sector osetdma:jmp setdma ;Set DM The fields * * are defined as follows: * * * * tracks This byte contains the number of tracks on the * * able are drive parameters for drives connected to * * the DJDMA floppy disk controller. There is one entry for each of * * thafter the heads have been stepped. Example, * * Shugart's SA 850 head settle time is 15 * * mi*********************************************************** * * * The following is the table of pointers to the Deviced be the * * drive manufactors recomended stepping delay times * * 34.1. Example. Shugart SA 850A address oread: jmp read ;Read the disk owrite: jmp write ;Write the disk jmp $ ;List device status osect: jmp sectran  drive. Most 8 inch drives have 77 tracks and * * most 5 1/4 inch drives have 35 or 40 tracks. * * e the eight drive that the controller can address. The first * * four entries are for the 8 inch drives and the last four are lliseconds. The settle constant would be 15 * * * 34.1 or 512. * * * * An assembler macro (DCONF) * * Specification Tables. The order of this table defines the * * logical order of the CP/M drives. * * * *'s step at 3 * * milliseond intervals. The step constant would be * * 3 * 43.1 or 102. * *  ;Sector translation jmp $ ;Hookup for SINGLE.COM program nop ;End of table **************************************** * * config This a a flag byte that indicates as to whether * * or not this drive has been configured. Sfor * * the 5 1/4 inch drives. Users with fast stepping 8 inch drives * * (SA850/1) or slow 5 1/4 inch drives (SA400) should  has been provided to assist in * * generating the DPARAM table. This macros parameters are the * * number of tracks, the s************************************************************************ dsttab: equ $ dn set 1 rept numprd order %dn  * * rfu The next two words are reserved for future use. * * They must be zero. * * * * settle This wor********************************* * * * Drive configuration table. * * * ******************************et to * * 0 to force reconfiguration. * * * * step This word contains the stepping rate constant. adjust this * * table for optimal device performace. * * * * Each table entry contains four fixed length fields. tep rate in milliseconds, and the head * * settle time in milliseconds. For example: * * * * ;Shugart SA 850  dn set dn+1 endm ************************************************************************* * * * The following td is similar to the previously defined * * step word. This specifies the head settle timing * * ******************************************* drconf: db 0 ;Revision 0 structure db 32 ;32 bytes long now ************** * * The DJDMA's delay routines tick 34.1 times per * * millisecond. Thus the step constant woul2  * * dconf 77, 3, 15 ;77 tracks, 3 ms step, 15 ms settle * * * * ;Shugart SA 400 * * dconf 35, 40, 10 ;35 trdconf 40, 5, 15 ;Drive 2 dconf 40, 5, 15 ;Drive 3 endif ******************************************************************************************************************** dconf 77, 8, 8 ;Drive 0 dconf 77, 8, 8 ;Drive 1 dconf 77, 8, 8****************** * * * Install packages drive select routine. This routine checks the * * external drive name to det the calibrated flag dw step*341/10 ;Step time dw 0 ;Reserved for future use, must be zero dw 0 ;Reserved for futurroutine inspects the command * * buffer for a drive specification. If present then the local * * drives are 'relocated' to acks, 40 ms step, 10 ms settle * * * * Note: Caution should be used when defining the drive parameters. * * Incorrec************ * * * DPH save area. Each entry is 4 bytes long: * * 0 - LSB of DPH address * * 1 - MSB of DPH ;Drive 2 dconf 77, 8, 8 ;Drive 3 ************************************************************************* * * etermine if the drive belongs to the host * * system or to the install drivers (local drives). The flag INSERV * * (in service use, must be zero dw settle*341/10 ;Head settle time endm dmarap: db 0, 10*8 ;Revision 0, length 80 bytes dparam:the user specified loaction. A 'map' * * of the drive configuration is printed. * * * ***************************t definations may damage the floppy disk drive. Morrow * * Designs takes no responsibility for damage that occures through *  address * * 2 - Sector size code (1 = 128, 2 = 256, 3 = 512... * * 3 - Bad map has been initilized (0 = Uninitilized)  * Define 5 1/4 inch drive parameters * * Use Tandon parameters: 40 tracks, 5 ms step, 15 ms settle * * * ******e) is set accordingly. If the drive belongs to the * * host system then the drive name is adjusted (so that the host * * sy equ $ ;Drive parameter table ************************************************************************* * * * Def********************************************** wboot: mvi a,0ffh ;One time code flag inr a jnz owboot sta wboot+1 ;* the misuse of this macro. * * * ************************************************************************* i* * * ************************************************************************* dphtab: rept maxlog dw 0, 0 end******************************************************************* dconf 40, 5, 15 ;Drive 0 dconf 40, 5, 15 ;Drive 1 stem does not know that we are here, shhh) and the host drive * * select routine is called. * * * **************ine 8 inch drive parameters * * Use SA800 parameters: 77 tracks, 8 ms step, 8 ms settle * * * ******************Clear one time flag jmp insetu ;Do install package setup routines *******************************************************f (maxdm ne 0) or (maxmf ne 0) ;DJDMA present? dconf macro tracks, step, settle db tracks ;Number of tracks db 0 ;Resm ************************************************************************* * * * Install package warm boot. This 3 *********************************************************** drvsel: mov a,c ;Get the external drive name lxi h,dlocal ;Tth byte. * * The revision byte is the current revision number for that * * particular structure and the length byte is the tall package variables. * * * ************************************************************************* dlocald on cold or warm boot * * * * 5) This will be a null (0) pointer. It marks the end of the * * table.  * Determine if the installed drivers are currently giving * * service to CP/M. If so then return else pop off return * * add* 1) This points to the drive configuration table. * * * * 2) This points to the I/O configuration bytes for the serest against the first local drive sub m jc drvsl1 ;Skip if the host drive is below us cpi maxlog ;See if this drive islength of that * * structure. This length does not include the revision byte nor * * the length byte itself. * * : db 16-maxlog ;First external drive used locally inserv: db 0 ;Local drive in service flag ****************************** * * ************************************************************************* if $ gt bios+256 ;Test for code ovress and jump to (hl). * * * ***************************************************************** serv: lda inserv ial * * drivers. Eg, the console, printer, reader, and punch * * devices. * * * * 3) This points within our range jnc drvsl0 mov c,a ;Load the local drive name mvi a,0ffh ;Set the in service flag jmp drvsl2 dr * * Revision Description * * E.0 1 and 2 defined * * E.3 This table is moved to a page boundry * * E.3 0, 3 an******************************************** * * * At the first page boundry following the IBIOS we have a series of *erlap 'Fatal error, pointer table placement.' else ds bios+256-$ ;Pad spaces till the next page endif db high ($-1)  ;Test the in service flag ora a rnz ;Return if we are servicing this one xthl ;Clear out the call to SERV donop:  to the drive parameter table for DJDMA floppy * * disk drives. If no DJDMA is present then this pointer is * * nvsl0: mov a,c ;Adjust the host drives above us sui maxlog mov c,a drvsl1: xra a ;Clear the in service flag drvsl2: sd 4 defined * * * * The pointers defined so far are as follows: * * * * 0) High byte is the page numbe * pointers that point to various internal tables. At the start of * * each of these tables we have a revision byte and a leng;IBIOS page number db revnum ;IBIOS revision number dw drconf ;Drive configuration table pointer dw 0 ;I/O configuratioret ;'jump' to the host call ************************************************************************* * * * Insull (0). * * * * 4) This points to the autostart command structures. Used to * * automatically invoke a commanta inserv ret ;Return to IBIOS's setdrv ***************************************************************** * * r of the IBIOS. Low byte is * * the IBIOS revision number. Used to determine pointer * * structure. * * * 4 n pointer (DELETED BY INSTALL) if (maxdm ne 0) or (maxmf ne 0) ;DJDMA present? dw dmarap ;Drive parameter table pointer e shld cpmtrk jmp osettrk ***************************************************************** * * * Sectran translauffer dirty flag ora a jnz dohome ;Skip buffer disable if buffer dirty xra a ;Invalidate buffer on home call sta bufsecal drive number sta cpmdrv cpi maxlog ;Check for a valid drive number jnc zret ;Illegal drive mov a,e ;Check if bi*********** * * * Setdma saves the DMA address for the data transfer. * * * *********************************ected it calls * * a low level drive select routine that should perform some * * sort of check if the device is working. If nlse dw 0 endif dw 0 ;Auto command structure pointer (DELETED) dw 0 ;End of table marker ***************************tes a logical sector number into a physical * * sector number. * * * ******************************************c dohome: lxi b,0 ;Track to seek to ***************************************************************** * * * Settrkt 0 of (e) = 1 ani 1 jnz setd3 ;Drive has allready been accessed mov h,c ;Move logical drive into (h) mvi l,d$sel1 ******************************** setdma: mov h,b ;Enter with DMA address in (bc) mov l,c shld cpmdma ;CP/M dma address ot working then * * it should report an error. If the logical drive has been * * selected before then setdrv just returns the************************************** * * * Setsec just saves the desired sector to seek to until an * * actual read *********************** sectran:lxi h,osect call serv lda cpmdrv ;Get the Drive Number mov h,a ;Drive in (h) mvi l, saves the track # to seek to. Nothing is done at this * * point, everything is deffered until a read or write. * * *  call jumper ;Call low level drive select mov a,h ;Check if the low level drive select returned ora l ; zero to indicate  jmp osetdma ***************************************************************** * * * Home is translated into a seek DPH without * * checking the drive. * * * ***************************************************************** sor write is attempted. * * * ***************************************************************** setsec: mov h,b ;d$stran jmp jumper ;See device level sector translation routines ********************************************************* ***************************************************************** settrk: mov h,b ;Enter with track number in (bc) mov l,can error jz zret ;Yes, an error so report to CP/M push h ;Save DPH address call gdph ;Get entry if DPH save table p to track zero. * * * ***************************************************************** home: lda bufwrtn ;Test betdrv: call drvsel ;Do INSTALL checking lxi h,osetdrv ;Vector to the host drive select call serv mov a,c ;Save the logiEnter with sector number in (bc) mov l,c shld cpmsec jmp osetsec ************************************************************** * * * Setdrv selects the next drive to be used in read/write * * operations. If the drive has never been sel5 op d ;DPH -> (de) mov m,e ;Put address of DPH in table inx h mov m,d inx h mov m,c ;Put sector size in table inx  ;Pick up current drive mov h,a ;Call drive routine to return a pointer to mvi l,d$bad ;the track and sector of the bad mave mov c,a lda cdisk ;Pick up user/drive ani 0f0h ;Save user number ora c ;Put together with old drive sta cdisk by device drives to indicate no bad ret ; sector map badptr: dw badmap ;Pointer to next available bad map entry ***** mov h,c ;Drive in (h) mvi l,d$sel2 ;Select drive call jumper call gdph ;Quick select pop d mov e,m ;DPH -> (de) uffer badl: ldax d ;Pick up an entry from the buffer ora a jz bade ;All done mov a,m ;Pick up entry from bad map tableh mov a,m ;Check if bad map has ever been read for this ora a ; drive cz getbad ;Never been read so read in bad map xp call jumper mov a,h ;If routine returns 0 then the device has ora l ; no bad sector map jz badret mov e,m ;Piret ***************************************************************** * * * Getbad - Check if a device has a bad map************************************************************ * * * Write routine moves data from memory into the bufferinx h mov d,m inx h mov c,m ;Sector size -> (c) xchg ;DPH -> (hl) jmp setd0 gdph: lda cpmdrv ;Return pointer to inr a jz overflo ;Bad map overflow lda cpmdrv ;Put drive in table mov m,a inx h lxi b,8 call movbyt ;Move the chg ;DPH -> (hl) setd0: mov a,c ;Move sector size code into (a) sta secsiz ;Save sector size xra a setd1: dcr c ;Crck up track number of bad sector map -> (de) inx h mov d,m inx h xchg shld cpmtrk xchg mov a,m ;Pick up sector nu. If the device has * * a bad sector map then append bad entries to end of badmap * * table. * * * ***********. If the * * desired CP/M sector is not contained in the disk buffer, the * * buffer is first flushed to the disk if it has ev DPH save area rlc ;Each entry is 4 bytes long rlc mov e,a mvi d,0 lxi h,dphtab ;DPH save area table dad d ;Add orest of information into the table jmp badl bade: shld badptr ;Restore new bad map pointer badret: pop d pop b ret eate number of (128 bytes/physical sector)-1 jz setd2 rlc ori 1 jmp setd1 setd2: sta secpsec ;Save for deblocking ldmber of of bad sector map inx h mov h,m mov l,a shld truesec call fill ;Read in bad sector map into the buffer jc b****************************************************** getbad: mvi m,1 ;Set drive initilized push b push d lda cpmdrv er been * * written into, then a read is performed into the buffer to get * * the desired sector. Once the correct sector is iffset ret ;(hl) = DPH save area for current drive zret: lxi h,0 ;Seldrv error exit lda lastdrv ;Get last selected dri overflo:lxi h,omes call message jmp badret omes: db 0dh, 0ah, 'BAD MAP OVERFLOW!', 0dh, 0ah, 0 nobad: lxi h,0 ;Used a cpmdrv ;Save current drive as old drive sta lastdrv ; in case of select errors ret setd3: push d ;Save DPH address adret ;Ingore the bad map if it can't be read lhld badptr ;Pick up bad map pointer lxi d,buffer ;Start at beginning of b6 n memory, the * * buffer written indicator is set, so the buffer will be * * flushed, then the data is transferred into the bu ani 80h ;Save only the side bit mov c,a ;Remember the side mov a,h ani 7fh ;Forget the side bit mov h,a dcx h ;he disk that * * contains the desired CP/M sector, then checks if it is the * * sector currently in the buffer. If no match is rc ;No good, return with error indication ***************************************************************** * * ontain the desired sector, the buffer is * * flushed to the disk if it has ever been written into, then * * filled with the separe jz move ;Yes, match. Go move the data ldax d ;Get a byte to compare cmp m ;Test for match inx h ;Bump pointers ffer. * * * ***************************************************************** write: lxi h,owrite call serv mov Temporary adjustment divloop:dcr b ;Update repeat count jz divdone ora a mov a,h rar mov h,a mov a,l rar ;Divi made, the * * buffer is flushed if necessary and the correct sector read * * from the disk. * * * ************** Move has been modified to cause either a transfer into or out * * the buffer. * * * **************************ctor from the disk that contains the * * desired CP/M sector. * * * *********************************************to next data item inx d jz dtslop ;Match, continue testing *************************************************************a,c ;Save write command type sta writtyp mvi a,1 ;Set write command jmp rwent ***************************************de the CP/M sector # by the size ; of the physical sectors mov l,a jmp divloop ; divdone:inx h mov a,h ora c ;Re**************************************************** redwrt: mvi b,0 ;The 0 is modified to contain the log2 secsiz equ $-1 *************************************** move: lda cpmsec ;Get the CP/M sector to transfer dcr a ;Adjust to proper sector ******************** read: lxi h,oread call serv xra a ;Set the command type to read rwent: sta rdwr ;Save command typ**** * * * Drive, track, and sector don't match, flush the buffer if * * necessary and then refill. * * * ************************** * * * Read routine to buffer data from the disk. If the sector * * requested from CP/M is istore the side bit mov h,a shld truesec ;Save the physical sector number lxi h,cpmdrv ;Pointer to desired drive,track, an ; of the physical sector size/128 ; on the currently selected disk lhld cpmsec ;Get the desired CP/M sector # mov a,hin buffer ani 0 ;Strip off high ordered bits secpsec equ $-1 ;The 0 is modified to represent the # of ; CP/M sectors pe ***************************************************************** * * * Redwrt calculates the physical sector on t ***************************************************************** call fill ;Fill the buffer with correct physical sector n the buffer, then the data is simply * * transferred from the buffer to the desired dma address. If * * the buffer does not cd sector lxi d,bufdrv ;Pointer to buffer drive,track, and sector mvi b,6 ;Count loop dtslop: dcr b ;Test if done with com7 er physical sectors mov l,a ;Put into HL mvi h,0 dad h ;Form offset into buffer dad h dad h dad h dad h dad h ************************************************************** prep: call alt ;Check for alternate sectors di ;Reset intmvi a,0 ;The 0 is modified to reflect if ; the buffer has been written into bufwrtn equ $-1 ora a ;Test if written int************************************************** * * * Fill fills the buffer with a new sector from the disk. * * ov128 ;Move the data, HL = destination ; DE = source mvi a,1 sta bufwrtn ;Set buffer written into flag mvi a,0 ;Chaddress mvi l,d$sdma call jumpbuf rwop: mvi l,0 ;Get operation address call jumpbuf pop b ;Restore the retry coun dad h lxi d,buffer ;Beginning address of buffer dad d ;Form beginning address of sectgr to transfer xchg ;DE = addreserrupts xra a ;Reset buffer written flag sta bufwrtn mvi b,retries ;Maximum number of retries to attempt retrylp:push o rz ;Not written, all done mvi a,d$write sta rwop+1 call prep ;Do the physical write sta error ;Set up the error  * ***************************************************************** fill: call flush ;Flush buffer first rc ;Checkeck for directory write writtyp equ $-1 dcr a ;Test for a directory write mvi a,0 rnz ;No error exit **************ter mvi a,0 ;No error exit status rnc ;Return no error dcr b ;Update the retry counter stc ;Assume retry count exps in buffer lxi h,0 ;Get DMA address, the 0 is modified t/ ; contain the DMA address cpmdma equ $-2 mvi a,0 ;The zerb ;Save the retry count mvi l,d$sel2 ;Select drive call jumpbuf lhld alttrk ;Track number -> (hl) mov a,h ;Testflag ret ***************************************************************** * * * Prep prepares to read/write the d for error lxi d,cpmdrv ;Update the drive, track, and sector lxi h,bufdrv lxi b,5 ;Number of bytes to move call movbyt *************************************************** * * * Flush writes the contents of the buffer out to the disk if * ired mvi a,0ffh ;Error return rz ;Return sad news mov a,b cpi retries/2 jnz retrylp ;Try again push b ;Save reto gets modified to contain ; a zero if a read, or a 1 if write rdwr equ $-1 ana a ;Test which kind of operation jnz i for track zero ora l push h ;Save track number mvi l,d$home cz jumpbuf pop b ;Restore track # mvi l,d$strk isk. Retries are attempted. * * Upon entry, H&L must contain the read or write operation * * address. * * * *** ;Copy the data lda rdwr ;Test read write flag ora a jz fread ;Skip write type check if reading lda writtyp ;0 = al * it has ever been written into. * * * ***************************************************************** flush: ry count mvi l,d$home ;Home drive after (retries/2) errors call jumpbuf pop b jmp retrylp ;Try again ***************nto ;Transfer data into the buffer outof: call mov128 lda error ;Get the buffer error flag ret into: xchg ; call mcall jumpbuf lhld altsec ;Sector -> (hl) mov b,h mov c,l mvi l,d$ssec call jumpbuf lxi b,buffer ;Set the DMA 8 loc, 1 = dir, 2 = unalloc sui 2 ;Test for an unallocated write rz fwritin:lda secsiz ;Check for 128 byte sectors dc******* * * * Check for alternate sectors in bad sector table. If an * * alternate sector is found replace alttrk andep scanning table till correct driver found inx h ;Bump (hl) to point to start of dispatch table pop d ;Real (hl) -> (delda bufsec ;Pick up LSB of buffer sector cmp m jnz altmis inx h ;Point to MSB of alternate sector lda bufsec+1 ;Pick uer with the drive number from bufdrv. * * * ***************************************************************** jumpbrnate sector so use selected sector shld alttrk lhld bufsec shld altsec ret alt2: push h ;Save current bad map entryr a rz ;No deblocking needed fread: mvi a,d$read sta rwop+1 call prep ;Read the physical sector the buffer sta err altsec with * * new sector number else pass along unaltered. * * * ************************************************) mov a,e ;Move offset number into (a) rlc ;Each entry is 2 bytes mov e,a ;Make an offset mvi d,0 dad d ;(hl) = *p MSB of buffer sector cmp m jnz altmis ;Found an alternate sector inx h ;Point to real info on the alternate sector luf:lda bufdrv ;Dispatch with bufdrv for drive mov h,a jumper: push d push b push h mov a,h ;Logical drive into (a)  address mov a,c ;Move drive into (a) cmp m ;Check if drive in table matches jnz altmis ;Does not match skip this entryor ;Set the error status ret ***************************************************************** * * * Jumpbuf, jum***************** alt: lxi h,badmap ;Address of bad map -> (hl) lda bufdrv ;Pick up drive number currently working on mo*Routine mov a,m ;Pick up address of handler for selected inx h ; function mov h,m mov l,a ;(hl) = *routine mov a,cxi d,alttrk xchg ;MOVLOP (de) = source, (hl) = dest push b lxi b,4 call movbyt ;Move alternate sector info in correct lxi d,dsttab ;Drive specification pointer table jumpl: mov c,a ;Save logical in (c) ldax d mov l,a inx d ldax d mo inx h ;Point to LSB of alternate track lda buftrk ;Pick up LSB of buffer track cmp m jnz altmis inx h ;Point to MSper are used to dispatch to a low level device * * subroutine. Jumper is called with the drive in (h) and the * * routine numv c,a ;Move drive into (c) for speed in search all: xchg lhld badptr ;Get bad map pointer xchg ; -> (de) mov a,d ;Ch ;Logical in (a) pop b ;Restore saved registers pop d pchl ********************************************************** place pop b pop h ret altmis: pop h ;Current alternate did not match lxi d,9 ;Bump pointer by the length of an entv h,a ;Get a DST pointer in (hl) inx d mov a,c ;Logical in (a) sub m ;Subtract from first entry in DST jnc jumpl ;KeB alternate track lda buftrk+1 ;Pick up MSB of buffer track cmp m jnz altmis inx h ;Point to LSB of alternate sector ber (see description above) in (l). It passes * * along the (bc) and (de) registers unaltered. Jumpbuf is * * a call to jumpeck if at end of bad map table cmp h jnz alt2 ;Still more mov a,e cmp l jnz alt2 ;Still more lhld buftrk ;No alte9 ry dad d jmp all ;Loop for more ***************************************************************** * * * Mover minter jmp message ;Continue until null reached ***************************************************************** *  ret ***************************************************************** * * * Utility routine to output the message p; Command port (51) idbuff equ 0 ;Initialize data buffer pointer rsect equ 1 ;Read sector wsect equ 5 ;Write sector ination in (de) dw 0b0edh ;ldir xchg ret ***************************************************************** * * ; Status port (50) tkzero equ 01h ;Track zero opdone equ 02h ;Operation done complt equ 04h ;Seek complete tmout eoves 128 bytes of data. Source pointer in DE, Dest * * pointer in HL. * * * ************************************* * * The following code is for the Diskus Hard disk * * * ***********************************************************ointed at by (hl) * * terminated with a null. * * * **************************************************************isbuff equ 8 ;Initialize header buffer pointer ; Function port (52) pstep equ 04h ;Step bit nstep equ 0ffh-pstep ;St * Return DPH pointer. Enter with (de) with DPH base address * * and (a) with logical drive number. Returns with DPH addressqu 08h ;Time out wfault equ 10h ;Write fault drvrdy equ 20h ;Drive ready index equ 40h ;Delta index ; Control port**************************** mov128: lxi b,128 ;Length of transfer movbyt: xra a ;Check if host processor is a Z80 adi 3****** if hdc3 ne 0 ;Want HDC3 or 4 controller included ? hdorg equ 50h ;Hard Disk Controller origin hdstat equ hdo*** message:mov a,m ;Get a character of the message inx h ;Bump text pointer ora a ;Test for end rz ;Return if donep bit mask null equ 0fch ;Null command ; Misc constants hdrlen equ 4 ;Sector header length seclen equ 512 ;Sector * * in (hl). * * * ***************************************************************** retdph mov l,a ;Move l (50) hdfren equ 01h ;Enable external drivers hdrun equ 02h ;Enable controllers state machine hdclok equ 04h ;Clock s jpo z80mov ;Yes, Its a Z80 so use block move m8080: ldax d ;Get a byte of source mov m,a ;Move it inx d ;Bump poinrg ;Disk Status hdcntl equ hdorg ;Disk Control hdreslt equ hdorg+1 ;Disk Results hdcmnd equ hdorg+1 ;Disk Commands he push h ;Save pointer to text mov c,a ;Output character in C call ocout ;Output the character pop h ;Restore the po data length ***************************************************************** * * * Device Specification Table for ogical drive into (l) mvi h,0 dad h ;Multiply by 16 (size of DPH) dad h dad h dad h dad d ;(hl) = pointer to DPH ource control bit, high = disk hdwprt equ 08h ;Write protect a drive ; Result port (51) retry equ 02h ;Retry flag ters inx h dcx b ;Update counter mov a,b ;Test for end ora c jnz m8080 ret z80mov: xchg ;Source in (hl), Destdskomp equ hdorg+2 ;Seek complete clear port (on HDC4) hdfunc equ hdorg+2 ;Function port hddata equ hdorg+3 ;Data port : HDCA controller driver * * * ***************************************************************** hddst: db maxhd*hdlo xra a ;HL/2 + HL (same as HL*1.5) mov a,h rar mov d,a mov a,l rar mov e,a dad d endif shld settle ;Savest if ready yet ani drvrdy jnz hdtdel if not fujitsu lxi h,0 ;Time one revolution of the drive mvi c,index in h call hdptr ;Get pointer to current track mov e,m ;Get current track mov m,c ;Update the track mov a,e ;Need to se hdldrv: sta hdcur ;Save logical disk call divlog ;Divide by logical disks per drive mov a,c sta hddisk ;Save newcntl ret hdhome: call hdptr ;Get track pointer mvi m,0 ;Set track to zero in hdstat ;Test status ani tkzero ;g ;Number of logical drives dw donop ;No warm boot for INSTALL dw hdtran ;Sector translation dw hdldrv ;First time e the count for timeout delay endif call hdhome hdl2: lda hdcur ;Load logical drive lxi d,dphhd0 ;Start of hard didstat ana c mov b,a ;Save current index level in B hdinxd1:in hdstat ana c cmp b ;Loop untill index level changes ek at all ? sub c rz cmc ;Get carry into direction jc hdtrk2 cma inr a if fujitsu hdtrk2: jmp accok else hd physical drive call hdptr ;Get track pointers mov a,m ;Get current track inr a ;Check if -1 jnz hdl2 ;Nope, allAt track zero ? rz ;Yes if not fujitsu hdstepo:in hdstat ;Test status ani tkzero ;At track zero ? jz hddelay select dw hddrv ;General select dw hdhome ;Home current selected drive dw hdseek ;Seek to selected track dw hdsec sk DPH's mvi c,3 ;Hard disk sector size equals 512 bytes jmp retdph dcrc: dcr c ;Conditional decrement C routine re jz hdinxd1 hdindx2:inx h in hdstat ;Start counting untill index returns to ana c ; previous state cmp b jnz hdindxtrk2: call accok jmp hddelay endif accok: mov b,a ;Prep for build call build sloop: ani nstep ;Get step pulse low ready accessed ori null ;Select drive out hdfunc mvi a,hdfren+hdclok ;Enable drivers out hdcntl mvi c,239 ;Wait 2 mvi a,1 stc call accok ;Take one step out jmp hdstepo else xra a jmp accok endif if not fujitsu hddela ;Select sector dw hddma ;Set DMA address dw hdread ;Read a sector dw hdwrite ;Write a sector dw nobad ;No bad t divlog: mvi c,0 divlx: sui hdlog rc inr c jmp divlx hddrv: sta hdcur call divlog ;Get the physical drive # h2 if m10 ;Memorex M10's have 40 ms head settle dad h ;HL*2 endif if m26 ;Shugart M26's have 30 ms head settle  out hdfunc ;Output low step line ori pstep ;Set step line high out hdfunc ;Output high step line dcr b ;Update r minutes for disk ready lxi h,0 hdtdel: dcx h mov a,h ora l cz dcrc jz zret ;Drive not ready error in hdstat ;Ty:lhld settle ;Get hddelay deloop: dcx h ;Wait 20ms mov a,h ora l inx h dcx h jnz deloop ret endif hdseek:sector map hdtran: mov h,b ;Sector translation is handled via mov l,c ; physical sector header skewwing inx h retdd2: mov a,c sta hddisk ;Select the drive ori null out hdfunc mvi a,hdfren+hdrun+hdclok+hdwprt ;Write protect out hd; epeat count jnz sloop ;Keep going the required # of tracks jmp wsdone hddma: mov h,b ;Save the DMA address mov l,c r command to finish mov b,a ani opdone jz process mvi a,hdfren+hdrun+hdclok ;Write protect out hdcntl in hdstat anx h in hddata mov m,a inx h in hddata mov m,a inx h dcr b jnz rtloop ret hdwrite:call hdprep ;Prepare heaect: db 0 ;Current physical sector number hdtrak: db 0ffh ;Track pointer for each drive db 0ffh ;All drive default to hdsec: mov a,c call divspt adi hdspt ana a cz getspt sta hdsect mov a,c sta head getspt: mvi a,hdspt dcr c ;Write protect out hdcntl mvi a,hdfren+hdrun+hdclok+hdwprt ;Write protect out hdcntl xra a ret hdptr: lhld hddisk  shld hdadd ret wsdone: in hdstat ;Wait for seek complete to finish ani complt jz wsdone in hdskomp ;Clear sdonei tmout ;Timed out ? stc rnz in hdreslt ani retry ;Any retries ? stc rnz xra a ret hdprep: in hdstat ander rc xra a out hdcmnd lhld hdadd mvi b,seclen/4 wtloop: mov a,m ;Move 4 bytes out hddata inx h mov a,m ou an uncalibrated db 0ffh ; state (ff) db 0ffh settle: dw 0 ;Time delay constant for head settle endif ****** ret divspt: mvi c,0 divsx: sui hdspt rc inr c jmp divsx endif hdread: call hdprep rc xra a out hdcmnd c ;Get a pointer to the current drives mvi h,0 ; track position xchg lxi h,hdtrak dad d ret build: lda head ;B bit on an HDCA4 ret if m26 hdsec: mvi a,01fh ;For compatibility with IBIOS revs. ; 2.3 and 2.4 ana c ;Mask i drvrdy stc rnz mvi a,isbuff ;Initialize pointer out hdcmnd call build ori 0ch out hdfunc lda head out hddatt hddata inx h mov a,m out hddata inx h mov a,m out hddata inx h dcr b jnz wtloop mvi a,wsect ;Issue write*********************************************************** * * * The following equates relate the Morrow Designs 2D/B ma out hddata out hddata mvi a,rsect ;Read sector command out hdcmnd call process rc xra a out hdcmnd mvi b,uild a controller command byte ral ral ral ral lxi h,hddisk ora m xri 0f0h ret hdcur: db 0 ;Current logicalin sector number (0-31) cz getspt ;Translate sector 0 to sector 32 sta hdsect ;Save translated sector number (1-32) mva ;Form head byte call hdptr ;Get pointer to current drives track mov a,m ;Form track byte out hddata ana a mvi  sector command out hdcmnd call process rc mvi a,wfault ana b stc rz xra a ret process:in hdstat ;Wait fo * * controller. If the controller is non standard (0F800H) * * only the FDORIG equate need be changed. * * * *****seclen/4 lhld hdadd in hddata in hddata rtloop: in hddata ;Move four bytes mov m,a inx h in hddata mov m,a in disk hdadd: dw 0 ;DMA address hddisk: db 0 ;Current physical disk number head: db 0 ;Current physical head number hdsi a,0e0h ;Get the head number ana c rlc rlc rlc sta head ;Save the head number getspt: mvi a,hdspt ret elseb,80h jz zkey mvi b,0 zkey: lda hdsect ;Form sector byte out hddata mov a,b out hddata mvi a,hdfren+hdrun+hdclok < ************************************************************ if maxfd ne 0 ;Include Discus 2D ? fdorig equ 0f800H ;Origid track dw fdssec ;Set sector dw fddma ;Set DMA address dw fdread ;Read a sector dw fdwrite ;Write a sector dwisters dreg equ io+1 cmdreg equ io+4 clrcmd equ 0d0h ***************************************************************** * ake new sector the requested sector pop d call sideone mvi a,80h ;Side two bit ora h ; and sector mov h,a ret k Jockey 2D write routine fdsel equ fdorig+1bh ;Disk Jockey 2D select drive routine fdtstat equ fdorig+21h ;Disk Jockey 2D t c ;Subtract sector number push psw ;Save adjusted sector jm sidetwo sidea: pop psw ;Discard adjusted sector pop b n of Disk Jockey PROM fdboot equ fdorig+00h ;Disk Jockey 2D initialization fdcin equ fdorig+03h ;Disk Jockey 2D character in nobad ;No bad sector map ***************************************************************** * * * Floppy disk warm * * Device Specification Table for the Disk Jockey 2D/B * * * ************************************************ fdldrv: sta fdlog ;Save logical drive mov c,a ;Save drive # mvi a,0 ;Have the floppies been accessed yet ? flopflg eerminal status routine fdstat equ fdorig+27h ;Disk Jockey 2D status routine fderr equ fdorig+2ah ;Disk Jockey 2D error, flas ;Restore sector requested pop d ;Restore address of xlt table sideone:xchg ;hl <- &(translation table) dad b ;bc =put routine fdcout equ fdorig+06h ;Disk Jockey 2D character out routine fdhome equ fdorig+09h ;Disk Jockey 2D track zero see boot loader * * * ***************************************************************** fdtran: inx b push d ;S***************** fddst: db maxfd ;Number of logical drives dw donop ;No warm boot for INSTALL dw fdtran ;Sector trqu $-1 ana a jnz flopok mvi b,17 ;Floppies havn't been accessed lxi h,fdboot ;Check if 2D controller is installed h led fdden equ fdorig+2dh ;Disk Jockey 2D set density routine fdside equ fdorig+30h ;Disk Jockey 2D set side routine fdram offset into table mov l,m ;hl <- physical sector mvi h,0 ret sidetwo:call fdgsid ;Check out number of sides jz sk fdseek equ fdorig+0ch ;Disk Jockey 2D track seek routine fdsec equ fdorig+0fh ;Disk Jockey 2D set sector routine fddma eqave table address push b ;Save sector # call fdget ;Get DPH for current drive lxi d,10 ;Load DPH pointer dad d manslation dw fdldrv ;Select drive 1 dw fdsel2 ;Select drive 2 dw fdlhome ;Home drive dw fdseek ;Seek to specifie mvi a,(jmp) clopp: cmp m ;Must have 17 jumps jnz zret inx h inx h inx h dcr b jnz clopp lxi d,fdinit ;Initial equ fdorig+400h ;Disk Jockey 2D RAM address dblsid equ 20h ;Side bit from controller io equ fdorig+3f8h ;Start of I/O regidea ;Single sided pop psw ;Retrieve adjusted sector pop b cma ;Make sector request positive inr a mov c,a ;Mu fdorig+12h ;Disk Jockey 2D set DMA address fdread equ fdorig+15h ;Disk Jockey 2D read routine fdwrite equ fdorig+18h ;Disov a,m inx h mov h,m mov l,a mov a,m ;Get # of CP/M sectors/track ora a ;Clear carry rar ;Divide by two sub= ization sequence lxi h,fdorig+7e2h ;Load address lxi b,30 ;Byte count call movbyt ;Load controller RAM mvi a,0ffh : lda fdlog ;Return proper DPH lxi d,dphfd0 jmp retdph fdsel2: sta fdlog mov c,a jmp fdsel fdlhome:mvi c,0 ;SeCheck double sided bit mov m,a ;Save sides flag lxi d,dpb128s ;Base for single sided DPB's jz sideok lxi d,dpb128d ; db 1 ;Sector desired db 0 ;Track desired db 0 ;Header image, track db 0 ;Sector db 0 ;Side db 0 ;Sectoent drive sta fdldst ;Save drive status ani 0ch ;Mask in sector size bits push psw ;Used to select a DPB rar lxiead loaded timeout dw 0 ;DMA address db 0 ;Double sided flag db 0 ;Read header flag db 07eh ;Drive select consta ;Start 1791 sta dreg mvi a,clrcmd ;1791 reset sta cmdreg mvi a,1 ;Set 2D initialized flag sta flopflg flopok: clect side 0 call fdside jmp fdhome ;Do actual home fdssec: push b ;Save sector number mov a,b ;Check side select Base of double sided DPB's sideok: xchg pop d ;(HL) -> DPB base, (DE) -> &DPH.DPB pop psw ;Offset to correct DPB ral r dw 0 ;CRC fdlog: db 0 fdldst: db 0 ;Floppy drive status byte fdlsid: rept maxfd db 0ffh ;Number of sides on e h,xlts ;Table of XLT addresses mov e,a mvi d,0 dad d push h ;Save pointer to proper XLT call fdget ;Get pointernt db 0 ;Drive number db 8 ;Current disk db 0 ;Head loaded flag db 9 ;Drive 0 parameters db 0ffh ;Drive 0 trall flush ;Flush buffer since we are using it lda fdlog ;Select new drive mov c,a call fdsel call fdlhome ;Recalibbit rlc ;Move high bit to bit zero ani 1 mov c,a call fdside ;Call select side 0/1 pop b jmp fdsec fdgsid: l ral ;Make 0, 10, 20, 30 mov c,a mvi b,0 ;Make offset dad b ;(hl) is now a DPB pointer xchg ;Put proper DPB aach drive 0/1 endm endif if (maxfd ne 0) or (maxdm ne 0) ************************************************************ to proper DPH pop d lxi b,2 ;Copy XLT pointer into DPH call movbyt lxi d,8 ;Offset to DPB pointer in DPH dad d ack address db 9 ;Drive 1 parameters db 0ffh ;Drive 1 track address db 9 ;Drive 2 parameters db 0ffh ;Drive 2 trrate the drive lxi h,1 ;Select sector 1 of track 2 shld truesec inx h shld cpmtrk xra a ;Make sure we are doing a xi h,fdlsid ;Side flag table lda fdlog ;Drive number push d mov e,a ;Make offset mvi d,0 dad d ;Offset to propeddress in DPH.DPB mov m,e inx h mov m,d lxi h,15 ;Offset to DPB.SIZ dad d mov c,m ;Fetch sector size code fdget***** * * * Xlts is a table of address that point to each of the xlt * * tables for each sector size. * * ;HL <- &DPH.DPB push h call fdgsid ;Get pointer to side flag table entry lda fdldst ;Get drive status ani dblsid ;ack address db 9 ;Drive 3 parameters db 0ffh ;Drive 3 track address db 9 ;Current parameters db 0 ;Side desired read sta rdwr call fill ;Fill in buffer with sector jc zret ;Test for error return call fdstat ;Get status on currr entry pop d mov a,m ;Set up flags ora a ret fdinit: dw 0 ;Initialization bytes loaded onto 2D/B dw 1800h ;H> * ***************************************************************** xlts: dw xlt128 ;Xlt for 128 byte sectors dw xlt256 ******************************************************************** ********************************************************,44,57,58,59,60 db 13,14,15,16,29,30,31,32 db 45,46,47,48 xlt124: db 0 db 1,2,3,4,5,6,7,8 db 25,26,27,28,29,30,31,32  defines a diskette as 512 byte sectors, * * double density, and single sided. * * * ************************************************** xlt128: db 0 db 1,7,13,19,25 db 5,11,17,23 db 3,9,15,21 db 2,8,14,20,26 db 6,12,18,24 db  * * The following DPB defines a diskette for 256 byte sectors, * * double density, and single sided. * * * * ;Xlt for 256 byte sectors dw xlt512 ;Xlt for 512 byte sectors dw xlt124 ;Xlt for 1024 byte sectors ********************************* * * * The following DPB defines a diskette for 128 byte sectors, * * single density, and single s db 49,50,51,52,53,54,55,56 db 9,10,11,12,13,14,15,16 db 33,34,35,36,37,38,39,40 db 57,58,59,60,61,62,63,64 db 17,18,19********************************************** dpb512s:dw 60 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 0 ;EXM4,10,16,22 xlt256: db 0 db 1,2,19,20,37,38 db 3,4,21,22,39,40 db 5,6,23,24,41,42 db 7,8,25,26,43,44 db 9,10,27,28,4************************************************************************ dpb256s:dw 52 ;CP/M sectors/track db 4 ;BSH ********************************************************* * * * Xlt tables (sector skew tables) for CP/M 2.2. These tided. * * * ************************************************************************* dpb128s:dw 26 ;CP/M sec,20,21,22,23,24 db 41,42,43,44,45,46,47,48 ************************************************************************* *  dw 280 ;DSM dw 127 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 32 ;CKS dw 2 ;OFF db 3 ;512 byte sectors *****5,46 db 11,12,29,30,47,48 db 13,14,31,32,49,50 db 15,16,33,34,51,52 db 17,18,35,36 xlt512: db 0 db 1,2,3,4,17,18,19db 15 ;BLM db 1 ;EXM dw 242 ;DSM dw 127 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 32 ;CKS dw 2 ;OFF db 2 ables * * define the sector translation that occurs when mapping CP/M * * sectors to physical sectors on the disk. There is tors/track db 3 ;BSH db 7 ;BLM db 0 ;EXM dw 242 ;DSM dw 63 ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 16 ;CK * * Each of the following tables describes a diskette with the * * specified characteristics. * * * ************************************************************************* * * * The following DPB defines a diskette as 102,20 db 33,34,35,36,49,50,51,52 db 5,6,7,8,21,22,23,24 db 37,38,39,40,53,54,55,56 db 9,10,11,12,25,26,27,28 db 41,42,43;256 byte sectors ************************************************************************* * * * The following DPBone skew table * * for each of the possible sector sizes. * * * **************************************************S dw 2 ;OFF db 1 ;128 byte sectors ************************************************************************* * ? 4 byte sectors, * * double density, and single sided. * * * **************************************************** db 15 ;BLM db 0 ;EXM dw 561 ;DSM dw 255 ;DRM db 0f0h ;AL0 db 0 ;AL1 dw 64 ;CKS dw 2 ;OFF db 3ctors/track db 4 ;BSH db 15 ;BLM db 0 ;EXM dw 486 ;DSM dw 255 ;DRM db 0f0h ;AL0 db 0 ;AL1 dw 64  DMA address intrqc equ 24h ;Set Interrupt request dmhaltc equ 25h ;Halt command bracha equ 26h ;Channel branch setcha dpb128d:dw 52 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 1 ;EXM dw 242 ;DSM dw 127 ;DRM db 0c0h ;AL0 endif ***************************************************************** * * * The following equates relate the Mor********************* dp1024s:dw 64 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 0 ;EXM dw 299 ;DSM dw 127 ;512 byte sectors ************************************************************************* * * * The following ;CKS dw 2 ;OFF db 2 ;256 byte sectors ************************************************************************* *  equ 27h ;Set channel address setcrc equ 28h ;Set CRC retry count rdtrck equ 29h ;Read track command wrtrck equ 2ah ; db 0 ;AL1 dw 32 ;CKS dw 2 ;OFF db 1 ;128 byte sectors ******************************************************row Designs DJDMA * * controller. * * * ***************************************************************** i ;DRM db 0c0h ;AL0 db 0 ;AL1 dw 32 ;CKS dw 2 ;OFF db 4 ;1024 byte sectors *****************************DPB defines a diskette as 1024 byte sectors, * * double density, and double sided. * * * *********************** * * The following DPB defines a diskette as 512 byte sectors, * * double density, and double sided. * * * Write track command serout equ 2bh ;Serial console ouput senabl equ 2ch ;Enable serial input trksiz equ 2dh ;Set number******************* * * * The following DPB defines a diskette as 256 byte sectors, * * double density, and double sf (maxdm ne 0) or (maxmf ne 0) dmchan equ 50h ;Default channel address dmkick equ 0efh ;Kick I/O port address rdsect eq******************************************** * * * The following DPB defines a diskette for 128 byte sectors, * * si************************************************** dp1024d:dw 128 ;CP/M sectors/track db 4 ;BSH db 15 ;BLM db 0  ************************************************************************* dpb512d:dw 120 ;CP/M sectors/track db 4 ;BSH of tracks setlog equ 2eh ;Set logical drives readm equ 0a0h ;Read from controller memory writem equ 0a1h ;Write to conided. * * * ************************************************************************* dpb256d:dw 104 ;CP/M seu 20h ;Read sector command wrsect equ 21h ;Write a sector command gstat equ 22h ;Get drive status dmsdma equ 23h ;Setngle density, and double sided. * * * *************************************************************************  ;EXM dw 599 ;DSM dw 255 ;DRM db 0f0h ;AL0 db 0 ;AL1 dw 64 ;CKS dw 2 ;OFF db 4 ;1024 byte sectors @ troller memory dmfstp equ 3*341/10 ;Fast stepping rate = 3 ms * 34.1 dmfset equ 15*341/10 ;Fast settling rate = 15 ms * 34ector the requested sector pop d call dmside1 mvi a,80h ;Side two bit ora h ; and sector mov h,a ret dmldrv:  ora a ;Clear cary rar ;Divide by two sub c push psw ;Save adjusted sector jm dmside2 dmsidea:pop psw ;Discard xchg ;Put DPB address in DPH mov m,e inx h mov m,d lxi h,15 dad d mov c,m dmget: lda dmlog lxi d,dphdm0 jm dw dmselr ;Select drive 2 dw dmhome ;Home drive dw dmseek ;Seek to specified track dw dmssec ;Set sector dw dmlxi b,2 ;Number of bytes to move call movbyt ;Move the address of XLT lxi d,8 ;Offset to DPB pointer dad d ;HL <- .1 n$dubl equ 80h ;Double density n$2side equ 40h ;2 sided drive serin equ 03eh ;Address of serial input data **sta dmlog call dminit ;Test for a drive jc zret lxi h,1 ;Select sector 1 of track 2 shld truesec inx h shld cpmt adjusted sector pop b ;Restore sector requested pop d ;Restor address of xlt table dmside1:xchg ;hl <- &(translatiop retdph ; ; The current drive is double sided. Thus is it safe to set the ; stepping rate to 3 ms with 15 ms settling. ;dma ;Set DMA address dw dmread ;Read a sector dw dmwrite ;Write a sector dw nobad ;No bad sector map dmselr: st&DPH.DPB push h call dmstat ani 20h ;Check double sided bit lxi d,dpb128s ;Base for single sided DPB's jz dmsok c*************************************************************** * * * Device Specification Table for the Disk Jockey DMrk xra a ;Make sure we are doing a read sta rdwr call fill ;Flush buffer and refill jc zret ;Test for error returnn table) dad b ;bc = offset into table mov l,m ;hl <- physical sector mvi h,0 ret dmside2:call dmstat ani 20h  sethigh:lhld dmlog ;Get the current drive number mvi h,0 dad h ;Ten bytes per parameter table entry mov d,h mov a dmlog mvi b,0 ;8 inch logical drives start at zero jmp dmsel2 dmtran: inx b push d ;Save table address push b all sethigh ;Set controller for fast steping lxi d,dpb128d ;Base of double sided DPB's dmsok: xchg ;HL <- DBP base, DE A floppy * * * ***************************************************************** if maxdm ne 0 dmdst: db maxdm ; call dmstat ;Get status on current drive ani 0ch ;Mask in sector size bits push psw ;Used to select a DPB rar  jz dmsidea pop psw ;Retrieve adjusted sector pop b cma ;Make sector request positive inr a mov c,a ;Make new se,l dad h dad h dad d lxi d,dparam+1 ;Parameter table address dad d ;Skip the track size byte mvi m,0 ;Force re ;Save sector # call dmget lxi d,10 dad d mov a,m inx h mov h,m mov l,a mov a,m ;Get # of CP/M sectors/track <- &DPH.DPB pop d ;Restore DE (pointer into DPH) pop psw ;Offset to correct DPB ral ral mov c,a mvi b,0 dad b Number of logical drives dw donop ;No warm boot for INSTALL dw dmtran ;Sector translation dw dmldrv ;Select drive 1  lxi h,xlts ;Table of XLT addresses mov e,a mvi d,0 dad d push h ;Save pointer to proper XLT call dmget pop d A paramitization of this drive inx h ;Offset to the Stepping rate constant mvi m,(low dmfstp) ;Fast stepping rate constant mflog mov c,a ;Get proper physical configuration byte mvi b,0 lxi h,mfscon dad b mov a,m sta mfpcon mov a,c for double sided select jmp dmssec dblflg: db 0 mfseek: xra a ;Clear double sided select sta dblflg lda mfpcon atus on track 0 pop psw ora a jnz mfl9 ;Non zero mvi a,90h ;Double density default configuration call dmstat  dw donop ;No warm boot for INSTALL dw mftran ;Sector translation dw mfldrv ;Select drive 1 dw mfsel2 ;Select drguration byte mov c,a mvi b,0 lxi h,mfscon dad b mvi a,n$dubl mov m,a sta mfpcon lxi h,1 ;Select sector 1 of inx h mvi m,(high dmfstp) lxi d,5 ;Skip over the reserved fields dad d mvi m,(low dmfset) ;Fast settling rate const;Shhh, pretend that nothing happened mvi b,4 ;5 1/4 inch drives start at drive 4 jmp dmsel2 mftran: lda mfpcon ani ni n$2side jz dmseek ;Only single sided mov a,c ;Move selected track in (a) sbi 35 ;Subtract by track by number of;If zero then determine sector size ani 80h ;Check density bit jnz mfl9 ;Its double density mvi a,10h ;Single densitive 2 dw dmhome ;Home drive dw mfseek ;Seek to specified track dw mfssec ;Set sector dw dmdma ;Set DMA address  track 0 shld truesec dcx h shld cpmtrk xra a ;Make sure we are doing a read sta rdwr call fill ;Flush buffer anant inx h mvi m,(high dmfset) call dmparm ;Set drive parameters for the SA850 ret endif ***********************n$dubl lxi h,mfxltd ;Point to double sided sectran table jnz mftdubl ;Single density sector translation lxi h,mfxlts m tracks jc dmseek ;Less than track 35 mov d,a ;Save adjusted track number mvi a,34 sub d ;Adjust to count tracksy configuration byte mfl9: mov c,a ;Move configuration byte into (c) lxi h,mfs ;Address of configuration table -> (hl dw dmread ;Read a sector dw dmwrite ;Write a sector dw nobad ;No bad sector map mfssec: dcr c ;Minnie floppy secd refill jc zret ;Test for error return lda buffer+5ch ;Get diskette configuration byte push psw ;Save configuratio****************************************** * * * Drive specification table for DJDMA 5 1/4 inch drives * * * ftdubl:dad b ;Add offset sector number to table mov l,m ;Pick up sector number from table mvi h,0 ;MSB of sector numbe back out mov c,a ;Resave new track number mvi a,0ffh ;Set double sided flag sta dblflg jmp dmseek mfsel2: sta ) mfl2: mov a,m ;Get an entry ora a ;Check for end of the table jz zret ;Yes, select error cmp c ;Check if entry tors start at zero lda dblflg ;Get double sided flags ora a jz dmssec ;Nope, single sided mvi b,80h ;Set high bit n byte lxi h,1 shld cpmtrk ;Load track 1 sector 1 call fill ;DJDMA firmware returns single density jc zret ; sta***************************************************************** if maxmf ne 0 mfdst: db maxmf ;Number of logical drivesr equal 0 ret mfldrv: sta mflog call dminit ;Test for a controller jc zret lda mflog ;Get proper physical confiB matches selected drive jz mfl3 inx h ;Skip onfiguration byte inx h ;Skip drive type inx h ;Skip DPB address inx +n$2side ;Double density, 35 tracks, two sided dw dpbmf3 ;2K groups db 0 ;End of configuration table mfxltd db 1,tar CP/M 2.x db n$dubl ;Double density, 35 tracks, one sided dw dpbmf2 ;2K groups db 0f0h ;North Star CP/M 2.x d out dmkick tests ora m jz tests ret dminit: lxi h,dmchan ;See if controller will halt mvi m,dmhaltc inx h mvi m,i 80h ;Check density bit mvi c,3 ;512 byte sectors rnz mvi c,2 ;256 byte sectors ret mfgdph lda mflog lxi d,d dmsel2: mov c,a ;Move drive into (c) lxi h,dmchan mvi m,setlog ;Set logical drives inx h mov m,b ;Drive in (b) h jmp mfl2 mfl3: inx h mov a,m ;Pick up drive type sta mfpcon mov e,a push h lda mflog ;Get proper physical 2, 3, 4 db 21,22,23,24 db 5, 6, 7, 8 db 25,26,27,28 db 9,10,11,12 db 29,30,31,32 db 13,14,15,16 db 33,34,35,36 b n$dubl+n$2side ;Double density, 35 tracks, two sided dw dpbmf3 ;2K groups db 0e5h ;North Star CP/M 1.4 db n$dubl 0 out dmkick ;Start controller lxi d,0 ;Set up timeout counter dminwt mov a,m ora a jnz dmiok ;Controller has resphmf0 jmp retdph mfpcon: db 0 ;Physical configuration byte mflog: db 0 mfscon: db 0, 0, 0, 0 ;Saved physical configu push b call docmd pop b jmp dmsel dmssec: push b ;Save sector number mov a,b rlc ani 1 mov c,a call dmside configuration byte mov c,a mvi b,0 lxi h,mfscon dad b mov m,e pop h inx h mov a,m inx h mov h,m mov l,a db 17,18,19,20 db 37,38,39,40 mfxlts db 1, 2 db 3, 4 db 5, 6 db 7, 8 db 9,10 db 11,12 db 13,14 db 15,1 ;Double density, 35 tracks, one sided dw dpbmf1 ;1K groups db 0a0h ;North Star CP/M 2.x (fake 40 track) db n$dublponded dcx d ;Bump timeout counter mov a,d ora e jnz dminwt stc ;Set error flag ret dmiok push h ;Set drivration bytes mfs: db 10h ;North Star CP/M 1.4 db 0 ;Single density, 35 tracks, one sided dw dpbmf0 ;1K groups d pop b jmp dmsec dmdma lxi h,dmchan ;Default channel address mvi m,dmsdma ;Set DMA address inx h mov m,c ;Low b ;DPB address -> (hl) push h ;Save DPB address call mfgdph ;Get DPH lxi d,10 ;Offset to DPB address in DPH dad d6 db 17,18 db 19,20 endif ***************************************************************** * * * Common routi ;Double density, 35 tracks, one sided dw dpbmf2 ;2K groups db 0d0h ;North Star CP/M 2.x (fake 40 track) db n$duble parameters call dmparm pop h dcx h ;Back to start of command mvi m,setcrc ;Disable monitor inx h mvi m,1 xra b 90h ;North Star CP/M 1.4 db n$dubl ;Double density, 35 tracks, two sided dw dpbmf1 ;1K groups db 0b0h ;North Syte first inx h mov m,b ;High byte next docmd xra a inx h mov m,a docmd2 inx h mvi m,dmhaltc inx h mov m,a  pop d mov m,e ;Store DPB address in DPH inx h mov m,d call mfgdph push h call dmstat ;Get status pop h annes for the DJDMA with 8 and 5 1/4 inch drives * * * ***************************************************************** C a jmp docmd2 ;Do command ; ; Set floppy drive parameters ; ; This routine reads the dparam table and if the a drive ha7 mov c,a ;Resave in (c) lda llss ani 7fh ;Mask out old side select bit jmp stores dmsel: mov a,c ;Move drive ipointer dad b xchg lxi b,16 ;Bump controller tables pointer dad b xchg pop psw ;Retrieve drive count dcr a  ;Put together with lower drive bits ora c mov c,a inx h mvi a,10h ;Double density bit ana m rlc ;20h rlc librated mode (0ffh) dcx h ;Back up to the track size byte shld dmntrk ;Set the number of tracks pointer inx h inx hve select LSB --------------------------+ ; dmstat lxi h,dmchan mvi m,gstat ;Set up read status inx h lda lldrv ;Gs not ; previously been calibrated then that drives track count, ; stepping rate, and head settling time are loaded. ; dmpnto (a) sta lldrv dmden: ret ;Double density only ; ; Return status in the (a) register in the form: ; ; 7 6 5  ;Bump count jnz dmstr0 ;Set up next drive ret dmhome xra a mov c,a ;Put a zero into (c) for track zero dmseek ;40h rlc ;80h for density bit ora c mov c,a inx h mvi a,3 ;Sector length mask ana m ;And in rlc ;Move t shld dmspar ;Set the stepping constants pointer xchg ;Set the local parameter table pointer shld dmloc0 inx h ;Oet last selected drive mov m,a ;Store drive in command inx h ;Skip over returned status inx h inx h call docmd ;arm: mvi a,8 ;Eight drives lxi d,1340h ;Start with drive 0's table lxi h,dparam+1 ;Drive parameter table dmstr0: pus5 3 2 1 0 ; ^ ^ ^ ^ ^ ^ ^ ^ ; Density --------------+ | | | | | | | ; Side select -------------+ | | | mov a,c ;Enter with track in (c) sta lltrk ;Save for use later ret dmsec lda llss ;Load sector ani 80h ;Save so bits 2 & 3 rlc ora c mov c,a inx h mvi a,4 ;Mask for double sided bit ana m rlc ;8 rlc ;10 rlc ;2ffset to the stepping parameters inx h inx h inx h shld dmloc1 lxi h,dmwcon ;Write the drive constants out lxi d,17Issue command lda llss ;Get side bit of last operation ani 80h rrc ;Move to bit 7 mov c,a lxi h,dmchan+1 ;Point h psw ;Save the drive count mov a,m ;Load flags ora a ;Does the drive need to be calibrated? jnz dmstr1 ;No, do no | | | ; Double sided ---------------+ | | | | | ; 5 1/4 -------------------------+ | | | | ; Sector size MSB ---ide select bit stores ora c sta llss ret dmside: mov a,c ;Move side bit into (a) ani 1 rrc ;Move around to bit 0 ora c ret dmwrite mvi a,wrsect db 01 ;Ugh... dmread mvi a,rdsect lxi h,dmchan lxi d,lltrk-1 mvi b,4 cload m ;Halt status offset call dmdoit pop d ;Retrieve the table pointers pop h dmstr1: lxi b,10 ;Bump parameter table to drive mov a,m ;Load drive ora c ani 4 ;Mask upper drive select bit for 5 1/4 rlc rlc ;Move to bit 4 ora m t fiddle around push h ;Save the parameter table pointer push d ;Save the controllers table pointer dcr m ;Set to ca---------------+ | | | ; Sector size LSB ---------------------+ | | ; Drive select MSB -----------------------+ | ; DriD ov m,a inx h inx d ldax d dcr b jnz cload dcx h call docmd lda dmchan+4 cpi 80h cmc ret ; ; Execute a te step delay headdly equ 0 ;Settle delay (0-25.5 milliseconds) endif if st412 ;Specifications for a Seagate ST412 cyl* * The follwing equates are for the HDDMA hard disk controller * * * ************************************************and2 equ 0c0h ;Precomp, high current band3 equ 80h ;precomp, low current track0 equ 1 ;Track zero status wflt equ 2 ;Writ ret dmwcon: db writem ;Write track size dmntrk: dw 0 ;Number of tracks + desync db 0 ;X-address dw 2 ;Two bytller commands dmaread equ 0 ;Read sector dmawrit equ 1 ;Write sector dmarhed equ 2 ;Find a sector dmawhed equ 3 ;Write hDJDMA command, no command status is returned ; ; Entry: ; DE = offset to the halt status ; HL = pointer to the start of th equ 306 heads equ 4 precomp equ 128 lowcurr equ 128 stepdly equ 0 steprcl equ 30 headdly equ 0 endif if cm5619 ;Sp***************** if maxmw ne 0 ;HDDMA controller present ? if st506 ;Specifications for a Seagate Technology 506 cyl eqe fault from drive dready equ 4 ;Drive ready sekcmp equ 8 ;Seek complete ************************************************es dmloc0: dw 0 ;Local controller address db writem ;Write stepping rate data dmspar: dw 0 ;Pointer to the stepping eaders (format a track) dmalcon equ 4 ;Load disk parameters dmassta equ 5 ;Sense disk drive status dmanoop equ 6 ;Null cone command ; ; Returns: ; nothing ; dmdoit: mvi a,bracha ;Branch channel command sta dmchan shld dmchan+1 ;Load comecifications for an CMI 5619 cyl equ 306 heads equ 6 precomp equ 128 lowcurr equ 128 stepdly equ 20 steprcl equ 30 headdlu 153 ;Number of cylinders heads equ 4 ;Number of heads per cylinder precomp equ 64 ;Cylinder to start write precomensation***************** * * * Drive Specification Table for the HD DMA hard disk controller * * * ******************parameters db 0 dw 8 dmloc1: dw 0 db dmhaltc ;Controller halt db 0 ;Status ; ; Driver variables ; lltrk dtroller operation reset equ 54h ;Reset controller attn equ 55h ;Send a controller attention chan equ 50h ;Default chanmand vector xra a ;Clear extended address sta dmchan+3 dad d ;Offset to the halt status mov m,a ;Clear the halt y equ 20 endif sectsiz equ 7 ;Sector size code (must be 7 for this IBIOS) ; 0 = 128 byte sectors ; 1 = 256 byt lowcurr equ 128 ;Cylinder to start low current stepdly equ 30 ;Step delay (0-12.7 milliseconds) steprcl equ 30 ;Recalibra*********************************************** mwdst: db maxmw*mwlog ;Number of logical drives dw donop ;No warm boot forb 0 llss db 1 lldrv db 0 dmlog db 0 endif ***************************************************************** * nel address stepout equ 10h ;Step direction out stepin equ 0 ;Step direction in band1 equ 40h ;No precomp, high current bstatus indicator out dmkick ;Start the controller dmwait: ora m ;Wait for the operation complete status jz dmwait e sectors ; 3 = 512 byte sectors ; 7 = 1024 byte sectors (default) ; f = 2048 byte sectors ;Define controE  INSTALL dw mwtran ;Sector translation dw mwldrv ;Select logical drive 1 (First time select) dw mwdrv ;Select logical dmvi m,headdly ;Head settle delay call mwissue ;Do load constants again call mwptr ;Get pointer to current cylinder number d ;(hl) = pointer to DPH mvi c,4 ;Return sector size of 1024 ret mwdrv sta mwcurl call mwdlog mov a,c sta mwdrivelxi h,0 ;Clear step counter shld dmastep ret mwdma mov h,b ;Set DMA address mov l,c shld dmadma ret mwsec mov MA controller. * * * ***************************************************************** mwldrv sta mwcurl ;Save cov h,b shld dmarg0 ;Set command channel cylinder number mov a,d inr a lxi h,0ffffh jnz mwskip0 mvi c,stepout jmp rive 2 (General select) dw mwhome ;Home current selected drive dw mwseek ;Seek to selected track dw mwsec ;Select secto mvi m,0ffh ;Fake at cylinder 65535 for max head travel inx h mvi m,0ffh lxi b,0 ;Seek to cylinder 0 call mwseek ;Re ;Save new selected drive mwsel mvi a,dmanoop jmp mwprep ;Execute disk command mwdlog: mvi c,0 mwllx: sui mwlog rc a,c ;Load sector number dcr a ;Range is actaully 0-16 call mwdspt ;Figure out head number -> (c) adi mwspt ;Make sectourrent logical drive call mwreset ;Reset controller card jc zret ;Controller failure lda mwcurl call mwdrv ;Select mwskip mwskip0:mov h,b ;(hl) = new track, (de) = old track mov l,c call mwhlmde mvi c,stepout mov a,h ani 80h ;Chr dw mwdma ;Set DMA address dw mwread ;Read a sector dw mwwrite ;Write a sector if heads > 2 ;Test if drive is big encal slowly jmp mwreset ;Back to fast stepping mode mwbad: lxi h,mwbtab ;Return pointer to bad sector location ret mwbinr c jmp mwllx mwstat mvi a,dmassta ;Sense status operation code jmp mwprep ;Execute disk command mwhome call mwreser number sta mwsectr mov a,c sta mwhead ;Save head number ret mwdspt mvi c,0 ;Clear head counter mwdsptx sui mwsptdrive jc zret ;Select error call mwstat ;Get drive status ani dready ;Check if drive ready jnz zret call mwhomeeck hit bit for negitive direction jnz mwsout ;Step in mvi c,0 jmp mwskip mwsout: call mwneghl mwskip: shld dmastep lough for a bad spot map dw mwbad ;Return bad sector map info else dw nobad endif ***********************************tab: dw 0 ;Track 0 dw 19 ;Head 2, sector 0 = (2 * SPT + 0) + 1 mwseek call mwptr ;Get track pointer mov e,m ;Get oldt ;Reset controller, do a load constants lxi h,dmarg1 ;Load arguments mvi m,steprcl ;Load step delay (slow rate) inx h  ;Subtract a tracks worth of sectors rc ;Return if all done inr c ;Bump to next head jmp mwdsptx mwreset lhld chan  ;Home drive lxi d,dphmw0 ;Start of hard disk DPH's lda mwcurl mov l,a mvi h,0 dad h dad h dad h dad h dad da mwdrive ora c sta dmasel0 mvi a,dmanoop ;No-operation command for the channel call mwprep ;Step to proper track ****************************** * * * The following are the lowest level drivers for the Morrow * * Designs Hard Disk D track number inx h mov d,m dcx h mov m,c ;Store new track number inx h mov m,b mov l,c ;Build cylinder word mF  ;Save the command channel for a while shld tempb lda chan+2 sta tempb+2 out reset ;Send reset pulse to controller lxess sta dmarg3 if 1 ;Set to 1 for MW error reporter mwissue call mwdoit ;Do desired operation rnc ;Do nothing if no d,precomp call mwhlcde jc mwpreps mvi c,band2 lxi d,lowcurr call mwhlcde jc mwpreps mvi c,band3 ;cylinder >  rnz ;Return error status xthl ;Waste some time xthl xthl xthl dcx d ;Bump timeout counter mov a,d ora e  inx h mvi m,sectsiz ;Sector size code inx h mvi m,dmalcon ;Load constants command call mwissue ;Do load constants t hexout: push psw ;Poor persons number printer rrc rrc rrc rrc call nibout pop psw nibout: ani 0fh adi '0' i h,dmachan ;Address of command channel shld chan ;Default channel address xra a sta chan+2 ;Clear extended address byte error push psw ;Save error info call hexout ;Print status call dspout ; and a space lxi h,dmachan mvi c,16 ;16 low_current mwpreps lda mwhead ;Load head address sta dmarg2 cma ;Negative logic for the controller ani 7 ;3 bits of jnz mwiloop ;Loop if still busy stc ;Set error flag ret mwptr lda mwdrive ;Get currently select drives track address pop h ;Restore the track number shld dmarg0 push psw ;Save status lhld tempb ;Restore memory used for the channel point cpi '9'+1 jc nibok adi 27h nibok: mov c,a jmp ocout mwdoit equ $ else mwissue equ $ ;Do a disk command, handl shld bios ;Set up a pointer to the command channel sta bios+2 lhld dmarg0 ;Save the track number push h lxi h,dmasebytes of status mwerr: push b push h mov a,m call hexout ;Print a byte of the status line call spout pop h pop b head select rlc ;Shove over to bits 2 - 4 rlc ora c ;Add on low current and precomp bits mov c,a lda mwdrive ;Load rlc mov e,a mvi d,0 lxi h,mwtab dad d ;Offset into track table ret mwtran: mov h,b mov l,c inx h ret mwer shld chan lda tempb+2 sta chan+2 pop psw ret mwread mvi a,dmaread ;Load disk read command jmp mwprep mwwrite timeouts + errors endif lxi h,dmastat ;Clear status byte mvi m,0 out attn ;Start the controller lxi d,0 ;Time l1 ;Load arguments lda mwdrive ;Get the currently selected drive ori 03ch ;Raise *step and *dir mov m,a ;Save in drive  inx h ;Bump command channel pointer dcr c jnz mwerr mvi c,0ah ;Terminate with a CRLF call ocout mvi c,0dh call oc drive address ora c ;Slap in drive bits sta dmasel1 ;Save in command channel head select lda mwsectr ;Load sector addrneghl:mov a,h cma mov h,a mov a,l cma mov l,a inx h ret mwhlmde:xchg call mwneghl xchg dad d ret mwhe mvi a,dmawrit ;Load disk write command mwprep: sta dmaop ;Save command channel op code mvi c,band1 lhld dmarg0 lxiout counter (65536 retries) mwiloop mov a,m ;Get status ora a ;Set up CPU flags rm ;Return no error (carry reset) stcselect register lxi d,5 ;Offset to dmarg1 dad d mvi m,stepdly ;Load step delay inx h mvi m,headdly ;Head settle delayout pop psw ;Restore error status ret dspout: call spout ;Print two spaces spout: mvi c,' ' ;Print a space jmp ocouG lcde:mov a,h cmp d rnz mov a,l cmp e ret mwtab equ $ ;Collection of track addresses rept maxmw db 0ffh ;Initi******* if maxhd ne 0 dphdsk set 0 ;Generate DPH's for the hdc3 hard disks rept maxhd ldsk set 0 rept hdlog dphgedw 0 ;Physical sector that contains CP/M sector error: db 0 ;Buffer's error status flag bufdrv: db 0 ;Drive that buffer bhdsectp/8*tracks/4-1 ;Number of groups per partition off set 1 rept hdlog dpbgen hd,%ldsk,%hdsectp,5,31,1,%dsm,511,0ffh,0 dmarg3 db 0 ;Fourth argument dmaop db 0 ;Operation code dmastat db 0 ;Controller status byte dmalnk dw dmachan ;Link addal value of * * 'off' should be adjusted accordingly. * * * * hdtrks = tracks - 1 * * * ************alize to (way out on the end of the disk) db 0ffh endm db 0ffh mwcurl db 0 ;Current logical drive mwdrive db 0ffh ;Cn hd,%dphdsk,dpbhd,%ldsk ldsk set ldsk+1 dphdsk set dphdsk+1 endm endm if hdpart ne 0 ;Use non-standard partitioning elongs to buftrk: dw 0 ;Track that buffer belongs to bufsec: dw 0 ;Sector that buffer belongs to alttrk: dw 0 ;Alternateffh,0,%off,3 off set off+tracks ldsk set ldsk+1 endm else ;Else use standard DPB's if m26 ne 0 dpbhd0 dw 1024 ;Cress to next command channel db 0 ;extended address endif ***************************************************************************************************************** if m10 ne 0 hdsectp equ 336 ;Sectors per track hdtrks equ 243 ;Turrently selected drive mwhead db 0 ;Currently selected head mwsectr db 0 ;Currently selected sector dmachan equ $ ;Comm ***************************************************************** * * * hdsectp is the number of 128 byte sectors per track altsec: dw 0 ;Alterante sector lastdrv:db 0 ;Last selected drive *************************************************P/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2015 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ***** * * * IBIOS ram locations that don't need initialization. * * * ***************************************otal data tracks endif if m20 ne 0 hdsectp equ 672 hdtrks equ 243 endif if m26 ne 0 hdsectp equ 1024 hdtrks and channel area dmasel0 db 0 ;Drive select dmastep dw 0 ;Relative step counter dmasel1 db 0 ;Head select dmadma dw 0 ;D cylinder. * * * * hdtrks is the total number of data cylinders. Eg. it is * * the number of cyliders on the drive m**************** * * * DPB and DPH area. * * * ********************************************************** ;CKS dw 1 ;OFF db 3 ;SECSIZ dpbhd1 dw 1024 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2015 ;DS************************** cpmsec: dw 0 ;CP/M sector # cpmdrv: db 0 ;CP/M drive # cpmtrk: dw 0 ;CP/M track # truesec:equ 201 endif ldsk set 0 ;Use non-standard partitioning tracks set hdtrks/hdlog ;Number of tracks per partition dsm set MA address db 0 ;Extended address dmarg0 db 0 ;First argument dmarg1 db 0 ;Second argument dmarg2 db 0 ;Third argument inus the number of * * cylinders that are used for the system. If the number of * * 'system tracks' is not one then the initiH M dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 64 ;OFF db 3 ;SECSIZ dpbhd2 dw 1024 ;CP/M sectors/tra maxfd dphgen fd,%dn,0,0 dn set dn+1 endm endif if maxdm ne 0 dn set 0 rept maxdm dphgen dm,%dn,0,0 dn set dn+1 dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 195 ;OFF db 3 ;SECSIZ endif endif endif ;End of HD Dpt mwlog dpbgen mw,%ldsk,%mwsecpt,5,31,1,%dsm,1023,0ffh,0ffh,0,%off,4 off set off+tracks ldsk set ldsk+1 endm else ;w 122 ;OFF db 3 ;SECSIZ endif if m20 ne 0 dpbhd0 dw 672 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM t 288 mwtrks set 305 endif if cm5619 ne 0 mwsecpt set 432 mwtrks set 305 endif dphdsk set 0 ;Generate DPH's fock db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2047 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 127  endm endif if maxmw ne 0 ***************************************************************** * * * mwsectp isPH's and DPB's if maxmf ne 0 dpbgen mf, 0, 20, 3, 7, 0, 04fh, 63, 0c0h, 0, 16, 3, 2 dpbgen mf, 1, 40, 3, 7, 0, 0a4hUse standard partitioning off set 1 ;Initial system track offset trkoff set 8192/(mwsecpt/8)+1 ;The number of tracks in a  dw 2036 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 1 ;OFF db 3 ;SECSIZ dpbhd1 dw 672 ;CP/Mr the HDDMA hard disks rept maxmw ldsk set 0 rept mwlog dphgen mw,%dphdsk,dpbmw,%ldsk dphdsk set dphdsk+1 ldsk set ldsk ;OFF db 3 ;SECSIZ endif if m10 ne 0 dpbhd0 dw 336 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 1 the number of 128 byte sectors per cylinder. * * mwsectp = 72 * heads * * * * mwtrks is the total number of data, 63, 0c0h, 0, 16, 2, 3 dpbgen mf, 2, 40, 4, 15, 1, 051h, 63, 80h, 0, 16, 2, 3 dpbgen mf, 3, 40, 4, 15, 1, 0a9h, 63, 80partition blocks set mwsecpt/8*mwtrks ;The number of blocks on the drive psize set trkoff*(mwsecpt/8) ;The number of blocks in sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 2036 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;C+1 endm endm if mwpart ne 0 ;Generate DPB's for a HDDMA hard disk ldsk set 0 ;Use non-standard partitioning tracks 269 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS dw 1 ;OFF db 3 ;SECSIZ dpbhd1 dw 336 ;CP/M secto cylinders. * * mwtrks = tracks - 1 * * * ***************************************************************** h, 0, 16, 2, 3 dn set 0 rept maxmf dphgen mf,%dn,dpbmf,%dn dn set dn+1 endm endif if maxfd ne 0 dn set 0 rept a partition ldsk set 0 rept blocks/8192 ;Generate some 8 megabyte DPB's dpbgen mw,%ldsk,%mwsecpt,5,31,1,2047,1023,0ffh,0KS dw 98 ;OFF db 3 ;SECSIZ dpbhd2 dw 672 ;CP/M sectors/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 1028 ;DSM set mwtrks/mwlog ;Number of tracks per partition dsm set mwsectp/8*tracks/4-1 ;Number of groups per partition off set 1 rers/track db 5 ;BSH db 31 ;BLM db 1 ;EXM dw 1280 ;DSM dw 511 ;DRM db 0ffh ;AL0 db 0ffh ;AL1 dw 0 ;CKS d if st506 ne 0 mwsecpt equ 288 ;Sectors per track mwtrks equ 152 ;Total data tracks endif if st412 ne 0 mwsecpt seI ffh,0,%off,4 off set off+trkoff blocks set blocks-psize ldsk set ldsk+1 endm blocks set blocks/4 if blocks gt 256 ;If th;Set buffer to unknown state sta bufwrtn ;Set buffer not dirty flag sta error ;Clear buffer error flag jmp owboot ;Dues jnc inse0 ;Use default configuration if not legal sta dlocal ;Bottom of the local drive list inx h ;Bump to the  mov a,d ;Test for drive overflow cpi 'A'+17 ;16 drives max jnc prhd1 ;Skip on overflow jmp prhd0 ;Press on to the************************* ************************************************************************* * * * Set up th of drives mvi d,0 ;External drive 0 mvi c,0 ;Start at host drive 0 ('A:') call prhost ;Print the host lines lxiere is any stuff left, then use it blocks set blocks-1 dpbgen mw,%ldsk,%mwsecpt,5,31,1,%blocks,1023,0ffh,0ffh,0,%off,4 endio host warm boot ; ; Print the disk configuration message. ; ; A: Host system drive B: ; B: DJDMA 8" drive 0 ; C: DJDMA next character inse0: mov a,m ;Test the message flag cpi 'X' cnz prhead ;Print the header if no x flag lxi d,badm next character prhd1: mvi m,0 ;Terminate the message lxi h,prmpt1 ;Print the local configuration call prmesg lxi e INSTALL package variables, set up the IBIOS * * * ***************************************************************** h,prmpt1-1 ;Replace all the '~'s with names lda dlocal ;Starting drive adi 'A' mov d,a prhd0: inx h ;Bump to the f endif endif buffer equ $ ************************************************************************* * * * A8" drive 1 ; D: DJDMA 8" drive 2 ; E: DJDMA 8" drive 3 ; F: DJDMA 5 1/4" drive 0 ; G: DJDMA 5 1/4" drive 1 ; H: DJDMA 5 1/4ap ;Clear out bad map stax d lxi h,badmap+1 lxi b,9*badsiz ;32 map entries call movbyt mvi m,0ffh ;End marker h,dlocal mov c,m ;Load the starting host drive mov a,c ;Figure the starting external drive adi maxlog mov d,a mvi ******** insetu: lxi sp,100h ;Set up a nice stack lxi h,buff mov a,m ;Get the text buffer contents ora a ;Test fonext character mov a,m ;Get a character from the message ora a ;Test for the end of the message jz prhd1 ;Skip at enll code placed here (the disk deblocking buffer) will dissapear * * the first time a disk read/write call is executed. However" drive 2 ; I: DJDMA 5 1/4" drive 3 ; J: HDDMA M10 drive 0, partition A ; L: HDDMA M10 drive 0, partition B ; ... ; prhexra a ;Select disk A sta cpmdrv lxi h,buff ;Set up initial DMA address call setdma xra a ;A <- 0 sta bufsec a,16 ;Figure the number of drives sub d jc prhd2 ;Skip if our drives went past drive P: mov e,a call prhost prhd2r no flags jz inse0 ;Drive names default to O:, P: sui 'A' ;Convert to binary drive value cpi 16 ;Test for legal vald cpi '~' ;Drive name marker jnz prhd0 ;Check out the next character mov m,d ;Load a name inr d ;Bump the name , it * * is safe to place one time initialization code here. * * * ************************************************ad: lxi h,prmpt0 ;Print a login message call prmesg lda dlocal ;Print host drives before local drives mov e,a ;NumberJ : ret ; ; Print a the assignment lines, C = starting host drive, ; D = Starting external drive, E = number of drives ;  if m10m ne 0 msprnt 'HDCA + Memorex M10', maxhd, hdlog else msprnt 'HDCA + Fujitsu M10', maxhd, hdlog endif endif i acr, alf ;;End of the configuration line mspart set mspart+1 ;;Bump the partition counter endm msdrv set msdrv+1 ;;Bumpuffer) ;Buffer for 512 byte sectors if (maxfd ne 0) or (maxdm ne 0) or (maxmw ne 0) ds 512 ;Additional space for 1k sec ora a rz ;Return if done push h ;Save the character pointer mov e,a ;Print a character via CP/M mvi c,cpmout 0h msprnt 'DJ2D/B @ F000', maxfd, 1 else if fdorig eq 0f800h msprnt 'DJ2D/B @ F800', maxfd, 1 else msprnt 'DJ2D/B @ prhost: mov a,e ;Test the count ora a rz ;Return if done mov a,d ;Load the External drive name adi 'A' sta prmpf m20 ne 0 msprnt 'HDCA + Fujitsu M20', maxhd, hdlog endif if m26 ne 0 msprnt 'HDCA + Shugart M26', maxhd, hdlog endif the drive counter endm endm prmpt0: db acr, alf, 'Morrow Designs installable IBIOS, revision ' db revnum/10+'@', '.', tor devices endif ***************************************************************** * * * Each bad map entry consi call bdos pop h inx h ;Bump the character pointer jmp prmesg msprnt macro dname, ndrive, npart ;Print a drive name ????', maxfd, 1 endif endif endif endif if dn eq dmorder ;Generate the DJDMA 8 message msprnt 'DJDMA 8"', maxdm, t2 mov a,c ;Load the host drive name adi 'A' sta prmpt3 push b ;Print a line push d lxi h,prmpt2 call prmesg  endif if dn eq mworder ;Generate the HDDMA's message if st506 ne 0 msprnt 'HDDMA + M5', maxmw, mwlog endif if st(revnum mod 10) + '0' db '.', acr, alf, alf, 0 prmpt1: equ $ ;Local drive configuration prompt dn set 1 ;Generate thsts of 9 bytes: * * Logical drive number (1 byte) * * Track number of bad sector (2 bytes) * * Sector number of bad semsdrv set '0' ;;Drive counter rept ndrive mspart set 'A' ;;Partition counter rept npart db '~: ', &dname, ' drive ', 1 endif if dn eq mforder ;Generate the DJDMA 5 1/4 message msprnt 'DJDMA 5 1/4"', maxmf, 1 endif dn set dn+1 end pop d pop b inr c ;Bump the host drive name inr d ;Bump the external drive name dcr e ;Bump the drive count jmp412 ne 0 msprnt 'HDDMA + M10', maxmw, mwlog endif if cm5619 ne 0 msprnt 'HDDMA + M16', maxmw, mwlog endif endif e drive messages rept numprd ;Cover all of our products if dn eq hdorder ;Generate the HDCA's message if m10 ne 0 ctor (2 bytes) * * Track number of alternate sector (2 bytes) * * Sector number of alternate sector (2 bytes) * * msdrv ;;Print name and drive # if npart gt 1 ;;Print partition #'s only if > 1 parts db ', partition ', mspart endif dbm db 0 ;End of message prmpt2: db ' : Host system drive ' prmpt3: db ' :', acr, alf, 0 db 0,0ffh,0 ds 512-($-b prhost ; ; Print a NULL terminated string via CP/M's conout routine ; prmesg: mov a,m ;Test for the end of the stringif dn eq fdorder ;Generate the 2D/B message if fdorig eq 0e000h msprnt 'DJ2D/B @ E000', maxfd, 1 else if fdorig eq 0f00K * ***************************************************************** badmap: ds badsiz*9+1 ;32 entries + end marker dirbu ;Generate CKS and ALV tables alloc mw,%dn,%alv,0 dn set dn+1 endm else ;Use standard partitioning dn set 0 trk if maxfd ne 0 dn set 0 rept maxfd alloc fd,%dn,75,64 dn set dn+1 endm endif if maxdm ne 0 dn set 0 rept maxhd*hdlog ;Generate CKS and ALV tables alloc hd,%dn,%alv,0 dn set dn+1 endm else ;Standard partitioning dn sef: ds 128 ;Directory buffer tempb: ds 16 ;A little temporary buffer **************************************************off set 8192/(mwsecpt/8)+1 psize set trkoff*(mwsecpt/8) rept maxmw blocks set mwsecpt/8*mwtrks rept blocks/8192 ;Ge maxdm alloc dm,%dn,75,64 dn set dn+1 endm endif if maxmf ne 0 dn set 0 rept maxmf alloc mf,%dn,22,16 dn set dnt 0 rept maxhd if m26 ne 0 alloc hd,%dn,252,0 dn set dn+1 alloc hd,%dn,252,0 dn set dn+1 alloc hd,%dn,256,0 dn set *************** * * * Allocation and checked directory table area * * * ************************************nerate some 8 megabyte ALV's alloc mw,%dn,256,0 blocks set blocks-psize dn set dn+1 endm blocks set blocks/4 if blo+1 endm endif if maxmw ne 0 if mwpart ne 0 ;Use non-standard partitioning tracks set mwtrks/mwlog ;Number of tracdn+1 endif if m10 ne 0 alloc hd,%dn,159,0 dn set dn+1 alloc hd,%dn,161,0 dn set dn+1 endif if m20 ne 0 alloc***************************** if maxhd ne 0 if hdpart ne 0 ;Use non-standard partitioning tracks set hdtrks/hdlog ;Nucks gt 256 ;Use the remainder blocks set blocks-1 alv set (blocks/8)+1 alloc mw,%dn,%alv,0 dn set dn+1 endif endm ks per partition dsm set mwsectp/8*tracks/4-1 ;Number of groups per partition alv set (dsm/8)+1 dn set 0 rept maxmw*mwlog hd,%dn,255,0 dn set dn+1 alloc hd,%dn,255,0 dn set dn+1 alloc hd,%dn,129,0 dn set dn+1 endif endm endif endif mber of tracks per partition dsm set hdsectp/8*tracks/4-1 ;Number of groups per partition alv set (dsm/8)+1 dn set 0 reptendif endif db 0 ;Force a complete hex file end L