cbios.asm 83 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270
  1. TITLE 'CBIOS for Monroe "Monty" microcomputer and CP/M 2.2'
  2. ;
  3. ; written by Bruce R. Ratoff
  4. ; 26 Broad Street
  5. ; Cranford, NJ 07016
  6. ; for Monroe Systems for Business
  7. ; The American Road
  8. ; Morris Plains, NJ 07950
  9. ;
  10. ; Last change: 2/8/1983 WGW
  11. ;
  12. false equ 0
  13. true equ not false
  14. ;
  15. version equ 2
  16. revision equ 27
  17. production equ true ; true if production run
  18. ;
  19. month equ 2
  20. day equ 8
  21. year equ 83
  22. ;
  23. ; v2.27 WGW 256K support
  24. ; v2.26 WGW Hard disk support, printer etx/ack and timeout, clock
  25. ; v2.25 WGW Added xon/xoff support on list device
  26. ; v2.24 BRR First release version
  27. ; v2.23 BRR Experimental versions from v2.20
  28. ;
  29. etxack equ true ; enable etx/ack code
  30. ulimit equ 81 ; upper block size limit (+1)
  31. ; for etx/ack mode
  32. llimit equ 77 ; lower block size limit
  33. ; for etx/ack mode w/esc seq.
  34. ;
  35. memorydisk equ true ; utilize top 64k as disk
  36. mdisk$base equ 60h ; uses top 4 bits in io$pmapa
  37. ;
  38. defaultpmapa equ 0 ; default program map A offset
  39. defaultpmapb equ 0 ; default program map B offset
  40. ;
  41. scanuser0 equ true ; ccp scan of user 0 on error
  42. mpmbdoscalls equ true ; enables mp/m bdos functions
  43. interrupts equ true ; enables timer interrupts
  44. coninterrupt equ true and interrupts ; enables console type ahead
  45. conbuffersize equ 64 ; size of console type ahead buffer
  46. eiconst equ true and interrupts ; puts an EI in lconst:
  47. todfunctions equ true and interrupts ; enable bdos tod functions
  48. displayclock equ true and todfunctions ; display tod clock on OC
  49. displayampm equ true and displayclock ; display as 12 hour AM/PM
  50. clockoff equ false ; disables default tod display
  51. ;
  52. clockattribute equ 0 ; see attributes below
  53. clockcolumn equ 65 ; clock display column
  54. ;
  55. ; Bit Description (Display Attribute)
  56. ; 7 (msb) no-op
  57. ; 6 Dim
  58. ; 5 Double width
  59. ; 4 Reverse video
  60. ; 3 Underline (or block graphics)
  61. ; 2 Blink
  62. ; 1-0 Select code
  63. ; 0 = Normal Character
  64. ; 1 = Double height bottom
  65. ; 2 = Double height top
  66. ; 3 = Graphics (Thin line or block)
  67. ;
  68. maxfloppy equ 4 ; 4 floppies
  69. maxharddisk equ 4 ; 2 hard disks (2 more for two 10M hard disks)
  70. ;
  71. if memorydisk
  72. maxdisk equ maxfloppy+maxharddisk+1
  73. mdrive equ 8 ; |10|
  74. else
  75. maxdisk equ maxfloppy+maxharddisk
  76. mdrive equ -1 ; |10|
  77. endif
  78. ;
  79. ;
  80. istacksize equ 32 ; bytes allocated to interrupt stack
  81. ;
  82. maclib diskdef ;get table generation macros
  83. maclib z80 ;get z80 instruction set
  84. maclib montyio ;get Monty port definitions
  85. ;
  86. ;
  87. debug equ false ;true if trap "calc mode" key into Z80MON
  88. reloc equ true ;true if assembling for MOVCPM
  89. msize equ 64 ;cp/m memory size in kilobytes
  90. ;
  91. sys$ram EQU 41H ; SELECT 16K-32K-16K PARTITION
  92. sys$video EQU 45H ; SELECT VIDEO RAM AT 3000 HEX
  93. ;
  94. ; "bias" is address offset from 2C00H for memory systems
  95. ; larger than 21K (referred to as "b" throughout the text).
  96. ; Note: In "standard" systems, this is the offset from 3400H.
  97. ;
  98. bias equ (msize-21)*1024
  99. ;
  100. if reloc
  101. ccp equ $ ;will be 0 w/o MAC +R switch, 100h with
  102. else
  103. ccp equ 2D00H+bias ;base of ccp
  104. endif
  105. bdosb equ ccp+800h ;base of bdos
  106. bdos equ ccp+806h ;entry to bdos
  107. bios equ ccp+1600h ;base of bios
  108. bdosaret equ bdosb+345h ;bdos function code return value
  109. ;
  110. cdisk equ 0004H ;current disk number 0=A,...,15=P
  111. iobyte equ 0003h ; i/o byte
  112. ;
  113. start$ctc3 equ 85h ; div 16 with time constant and interrupt
  114. oneslice equ 250 ; time constant
  115. onetick equ 15 ; sub-interval to get 20 msec
  116. onesecond equ 50 ; 20 msec clock tick, 50 ticks/second
  117. ;
  118. maxrtr equ 5 ;max retries on floppy error
  119. rate equ 1 ;seek rate select (12 ms)
  120. if interrupts
  121. montime equ 15 ; seconds by timer interrupt
  122. else
  123. montime equ 10 ;tick count for motor timeout
  124. endif
  125. ;
  126. ; --- ASCII character codes -----
  127. ;
  128. etx equ 3
  129. ack equ 6
  130. bell equ 7
  131. bs equ 8
  132. lf equ 10
  133. ff equ 12
  134. cr equ 13
  135. xon equ 17 ; control-q
  136. xoff equ 19 ; control-s
  137. esc equ 27 ; escape
  138. control equ 1fh ; control characters
  139. ;
  140. ; ---- Additional implemented BDOS function codes -----
  141. ;
  142. settime equ 104
  143. readtime equ 105
  144. returnserial equ 107
  145. readclock equ 155
  146. ;
  147. ;
  148. ; ---- XEBEC COMMAND CONSTANTS ------
  149. ;
  150. TSTDR EQU 0
  151. RESTR EQU 1
  152. RQSEN EQU 3
  153. SEEK EQU 0BH
  154. RDSEC EQU 08
  155. WRSEC EQU 0AH
  156. CHKTK EQU 05H
  157. FORBD EQU 07H
  158. SETDR EQU 0CH
  159. ;
  160. DRVSEL1 EQU 20H
  161. ;
  162. ; GORMAN INTERFACE STATUS
  163. ;
  164. CSTAT EQU 4
  165. CDONE EQU 2
  166. GCMD EQU 1
  167. CBUSY EQU 80H
  168. ;
  169. DTAREQ EQU 40H
  170. ERHDK EQU 2
  171. ;
  172. ; GORMAN-XEBEC PORT ASIGNMENTS
  173. ;
  174. HD$DATA EQU 78H
  175. STCS EQU 79H
  176. ENDMA EQU 7AH
  177. DISDMA EQU 7BH
  178. ENINT EQU 7CH
  179. DISINT EQU 7DH
  180. ;
  181. SEL EQU 79H
  182. ;
  183. DMAMSK EQU 0FCH
  184. DMAHD EQU 03
  185. ;
  186. ; Macro to generate correct ORG statements for reloc or non-reloc sys
  187. rorg macro x
  188. if reloc
  189. org x-ccp
  190. else
  191. org x
  192. endif
  193. endm
  194. ;
  195. ; The following code generates the boot header sector required
  196. ; by the IPL ROM.
  197. ; It normally resides in track 0, sector 1 of a system disk.
  198. ;
  199. HORG equ CCP-100H ; Boot location rel. to CCP
  200. rorg HORG+0EH ; Set BIOS entry point
  201. db BIOS/256,BIOS and 0FFH
  202. rorg HORG+1EH
  203. dw 0FFFFH ; Flag this as a CP/M disk
  204. rorg HORG+82h ; Set load address
  205. db CCP/256,CCP and 0FFH
  206. if debug ; Set load length
  207. db code$size/256+7,code$size and 0FFH
  208. else
  209. db code$size/256,code$size and 0FFH
  210. endif
  211. ;
  212. ;
  213. ; The patches below cause the CCP to automatically search IPL drive
  214. ; for any .COM file not found on the current default drive.
  215. ;
  216. ccp$get$user equ ccp+113h ; ccp entry points
  217. ccp$set$user equ ccp+115h
  218. ;
  219. ccp$jnz$user0 equ ccp+6adh ; patch point
  220. ccp$user0 equ ccp+6c4h
  221. ccp$start$com equ ccp+6cdh
  222. ccp$jz$userer equ ccp+6dbh ; patch point
  223. ccp$jnz$load1 equ ccp+6ech ; patch point
  224. ccp$load1 equ ccp+701h
  225. ccp$userer equ ccp+76bh
  226. ccp$com$fcb equ ccp+7cdh
  227. ccp$sdisk equ ccp+7f0h
  228. ccp$end equ ccp+7f2h ; patch point
  229. ;
  230. ;
  231. rorg ccp$jz$userer
  232. jz ccppatch ; Taken if .COM not found
  233. ;
  234. ;
  235. if scanuser0
  236. rorg ccp$jnz$user0
  237. jnz ccp$jnz$user0$patch ; jump to patch location
  238. ;
  239. rorg ccp$jnz$load1
  240. jnz ccp$load1$patch ; jump to patch location
  241. endif ; end of scan user 0 option
  242. ;
  243. ;
  244. rorg ccp$end ; top of ccp section (14 free bytes)
  245. ccp$patch: ; use unaccessed ccp section
  246. lda ccp$auto$retry ; a := ccp auto retry flag
  247. ora a ; see if zero
  248. jz ccp$userer ; error if retries not allowed
  249. jmp continue$ccp$patch
  250. ;
  251. ; This patch allows the SUBMIT file ($$$.SUB) to reside on the IPL drive
  252. ;
  253. rorg ccp+140h ; in READCOM was
  254. lda ipldsk ; lda cdisk
  255. nop ; ora a
  256. nop ; mvi a,0
  257. nop
  258. db 0cdh ; cnz (now a call)
  259. ;
  260. rorg ccp+17dh ; in READCOM was
  261. lda ipldsk ; lda cdisk
  262. ora a ; ora a
  263. db 0cdh ; cnz
  264. ;
  265. rorg ccp+1e5h ; in DEL$SUB
  266. nop ; patches over: xra a
  267. call ccppat3 ; patches over: call select
  268. ;
  269. ; These patches force IPL drive to be selected after any BDOS error
  270. ;
  271. rorg bdosb+0a2h
  272. dw permerr
  273. ;
  274. rorg bdosb+0b8h
  275. dw permerr
  276. ;
  277. ; This patch changes the drive selected by the "disk reset" function
  278. ; to be the drive that the system was booted from, rather than A:
  279. ;
  280. rorg bdosb+0c8dh
  281. jmp rstpatch
  282. ;
  283. rorg bdosb+0df7h
  284. rstpatch:
  285. lda ipldsk
  286. sta bdosb+0342h
  287. jmp bdosb+0c90h
  288. ;
  289. ; This patch allows the mp/m bdos calls to be operable.
  290. ;
  291. if mpmbdoscalls
  292. rorg bdosb+33h ; place where bdos checks function code
  293. jmp bdospatch ; use internal check of limits
  294. bdosfunc: ; enter here if bdos function is ok
  295. endif
  296. ;
  297. ;
  298. ;
  299. rorg bios ;origin of this program
  300. ;
  301. ; jump vector for individual subroutines
  302. jmp boot ;cold start
  303. wboote: jmp wboot ;warm start
  304. xconst: jmp lconst ;console status
  305. xconin: jmp lconin ;console character in
  306. xco: jmp lconout ;console character out
  307. jmp llist ;list character out
  308. jmp lpunch ;punch character out
  309. jmp lreader ;reader character out
  310. jmp home ;move head to home position
  311. jmp seldsk ;select disk
  312. jmp settrk ;set track number
  313. jmp setsec ;set sector number
  314. jmp setdma ;set dma address
  315. jmp read ;read disk
  316. jmp write ;write disk
  317. jmp llistst ;return list status
  318. jmp sectran ;sector translate
  319. ;
  320. ; Physical driver variables:
  321. ; (Placed here in case maintenance utilities need them.)
  322. fpyctrl: ds 1 ;current select/control port value
  323. timecntr: ds 1 ;motor off delay count (0 if inactive)
  324. ipldsk: ds 1 ;IPL drive - default for warm boot
  325. bufptr: ds 2 ;used by COPY utility do not move |10|
  326. trktbl: db 255,255,255,255 ;current track on each drive
  327. fpycmd: ds 1 ;current floppy command
  328. timecntp: ds 2 ;motor off delay prescale count
  329. fpyrtry: ds 1 ;retry count for seek, read, write
  330. ;
  331. ; Default CTC and SIO divider control bytes for serial ports
  332. rbaud: db 78,0c4h ;modem baud rate control (300 baud)
  333. cbaud: db 10,44h ;aux console baud rate control (9600 baud)
  334. lbaud: db 78,44h ;printer baud rate control (1200 baud)
  335. ;
  336. ; Function key translate table pointer
  337. ukptr: dw uktbl ;reset to uktbl at every warm boot
  338. ;
  339. ; Sector translate table NOW FOR FLOPPY ONLY
  340. xltbl: db 0,1,8,9,16,17,24,25
  341. db 2,3,10,11,18,19,26,27
  342. db 4,5,12,13,20,21,28,29
  343. db 6,7,14,15,22,23,30,31
  344. ;
  345. enableetxack: db 0 ; 0ffh enables etx/ack printer support
  346. lsize: db 0 ; current line size with etx/ack mode
  347. ;
  348. ccp$auto$retry: db true ; ccp auto retry on .com file load
  349. ;
  350. logical$disk: ; logical to physical disk table
  351. db 0, 1, 2, 3 ; A:, B:, C:, D: (floppies)
  352. hd$drvs: ; |10|
  353. db 4, 5,-1,-1 ; E:, F:, G:, H: (hard disk)
  354. db -1,-1,-1,-1 ; I:, J:, K:, L: (not used)
  355. db mdrive,-1,-1,-1 ; M:, N:, O:, P: (memory disk) |10|
  356. ;
  357. pmapa$current: db defaultpmapa ; current value of io$pmapa
  358. pmapb$current: db defaultpmapb ; current value of io$pmapb
  359. sys$current: db sys$ram ; current value of io$sys
  360. cpm$system: db sys$ram ; current value while running cpm
  361. ; can be changed to sys$video to
  362. ; select video ram at 3000 hex
  363. cpm$video: db sys$video ; current value while running cpm to
  364. ; select video ram at 3000 hex
  365. ;
  366. ;
  367. second$interrupt: ; for system programs ONLY
  368. if displayclock
  369. if clockoff
  370. ret ; patch to jump to enable display
  371. dw displaytod ; possible jump location
  372. else
  373. jmp displaytod ; display time of day
  374. endif
  375. else
  376. ret ; Call made here each second.
  377. dw 0 ; Can be patched with a jump location
  378. ; Only three stack levels available,
  379. ; all 8080 registers saved
  380. endif
  381. ;
  382. inputpointer: db 0 ; console buffer input pointer
  383. outputpointer: db 0 ; console buffer output pointer
  384. ;
  385. mem$hcol: db 80h ; buzzer/hi-res/char video enable port copy
  386. ;
  387. lstsec: db 0ffh ; list time-out in seconds (0ffh is off)|14|
  388. lstcnt: db 0 ; list time-out counter |14|
  389. ;
  390. ;
  391. ; XEBEC CONTROL BLOCK
  392. DCB$CMD: DS 1 ;COMMAND SAVE BYTE.
  393. DCB$DRV: DS 1 ;DRIVE AND MS ADDR
  394. DCB$CTRK: DS 2 ;CURRENT LOGICAL ADDRESS
  395. DCB$NSEC: DB 1 ;NUMBER OF SECTORS TO XFER
  396. DCB$CTL: db 0 ;CONTROL BYTE |10|
  397. DCB$RSTA: DS 1 ;RETURNED STATUS
  398. DCB$RTRK: DS 3 ;RETURNED LOGICAL ADDRSS
  399. DCB$RTRY: DS 1 ;RETRY COUNTER
  400. ;
  401. ;
  402. if interrupts
  403. tod: dw 0 ; days since Jan. 1, 1978
  404. todhours: db 0 ; hours (BCD)
  405. todminutes: db 0 ; minutes (BCD)
  406. todseconds: db 0 ; seconds (BCD)
  407. db onesecond
  408. todticks: db onetick ; ticks
  409. interruptsp: dw 0 ; sp during clock interrupt
  410. ds istacksize ; interrupt stack (see next label)
  411. if (low $) gt 0d0h ; interrupt vectors start at xx0dh
  412. rorg <1D0h+(0ff00h and $)> ; on next page
  413. else
  414. rorg <0d0h+(0ff00h and $)> ; on this page
  415. endif
  416. interruptstack: ; interrupt stack grows down
  417. vectortbl:
  418. dw doreti ; SIO B (D0) Transmit Ready (Auxillary)
  419. dw doreti ; Status Change
  420. dw doreti ; Receiver Ready
  421. dw doreti ; Special Reciver Condition
  422. dw doreti ; SIO A (D8) Transmit Ready (Communication)
  423. dw doreti ; Status Change
  424. dw doreti ; Receiver Ready
  425. dw doreti ; Special Reciver Condition
  426. if coninterrupt
  427. dw consoleint ; Dart B (E0) Transmit Ready (Keyboard)
  428. dw consoleint ; Status Change
  429. dw consoleint ; Receiver Ready
  430. dw consoleint ; Special Reciver Condition
  431. else
  432. dw doreti ; Dart B (E0) Transmit Ready (Keyboard)
  433. dw doreti ; Status Change
  434. dw doreti ; Receiver Ready
  435. dw doreti ; Special Reciver Condition
  436. endif
  437. dw doreti ; Dart A (E8) Transmit Ready (Printer)
  438. dw doreti ; Status Change
  439. dw doreti ; Receiver Ready
  440. dw doreti ; Special Reciver Condition
  441. dw doreti ; Ctc 0 (F0)
  442. dw doreti ; Ctc 1 (F2)
  443. dw doreti ; Ctc 2 (F4)
  444. dw clockint ; Ctc 3 (F6)
  445. dw doreti ; PIO A (F8)
  446. dw doreti ; PIO B (FA)
  447. dw doreti ; not used (FC)
  448. dw doreti ; External (Maybe FE)
  449. ;
  450. if coninterrupt
  451. consoleint:
  452. sspd interruptsp ; save user sp
  453. lxi sp,interruptstack
  454. push psw ; save parameters
  455. push b
  456. push d
  457. push h
  458. in io$drtbd ; a := character entered
  459. mov c,a ; c := character entered
  460. lxi h,outputpointer ; hl := output pointer index
  461. mov d,m ; d := output pointer
  462. dcx h ; hl := input pointer index
  463. mov e,m ; l := current input pointer
  464. mov a,e ; a := current input pointer
  465. inr a ; increment pointer
  466. cpi conbuffersize ; check for pointer overflow
  467. jrc concheckbuffer
  468. sub a ; a := 0 (start of buffer)
  469. concheckbuffer:
  470. cmp d ; compare to output pointer
  471. jrz conrestore ; exit if buffer is full
  472. mov m,a ; update input pointer
  473. mvi d,0 ; de := current input pointer
  474. lxi h,conbuffer ; hl := base of console buffer
  475. dad d ; hl := buffer index
  476. mov m,c ; update buffer
  477. conrestore:
  478. pop h ; restore parameters
  479. pop d
  480. pop b
  481. pop psw
  482. lspd interruptsp ; restore user stack
  483. ei ; enable interrupts
  484. reti ; resume execution
  485. endif
  486. clockint: ; main timer interrupt for clock and timeout
  487. sspd interruptsp ; save user sp
  488. lxi sp,interruptstack
  489. push psw ; save state on interrupt stack
  490. push h
  491. lxi h,todticks ; hl := tod ticks index
  492. dcr m
  493. jrnz noclocktick ; check the rest of the clock each tick
  494. push b ; save user bc and de
  495. push d ; all primary registers saved
  496. call clocktick ; do real operation
  497. pop d ; restore user registers
  498. pop b
  499. noclocktick:
  500. pop h ; restore user regisers
  501. pop psw
  502. lspd interruptsp ; restore user stack
  503. doreti: ei ; turn on interrupts
  504. reti ; resume
  505. clocktick:
  506. mvi m,onetick ; update tick counter
  507. dcx h ; index slice counter
  508. dcr m ; decrement slice count
  509. rnz ; exit if not one second
  510. mvi m,onesecond ; update tick count
  511. if todfunctions ; select if mp/m bdos tod functions
  512. call updatetod ; update clock (hl = base of tod block)
  513. call second$interrupt ; possible user routine
  514. endif
  515. call chklist ; check list time-out every second
  516. jmp chkmotor ; check disk drive motor every second
  517. chklist: lxi h,lstcnt ; hl := list time-out counter index
  518. mov a,m ; a := list time-out counter
  519. ora a ; time-out occurred?
  520. rz ; exit on time-out
  521. inr a ; counter off? (a was 0ffh)
  522. rz ; exit if counter turned off
  523. dcr m ; else decrement counter
  524. ret
  525. if todfunctions
  526. updatetod: ; update time-of-day clock
  527. mvi e,60h ; e := seconds/minutes limit
  528. call checktoddigit ; check seconds
  529. cnc checktoddigit ; check minutes (skip if seconds < 60)
  530. mvi e,24h ; e := hours limit
  531. cnc checktoddigit ; check hours (skip if sec/min < 60)
  532. rc ; check days, exit if still today
  533. dcx h ; otherwise, increment day count
  534. dcx h ; index lsb of tod days
  535. inr m ; increment lsb
  536. rnz ; exit if no overflow
  537. inx h ; index msb of tod days
  538. inr m ; increment msb
  539. ret ; all done
  540. checktoddigit:
  541. dcx h ; index next digit
  542. mov a,m ; increment next digit(BCD)
  543. adi 1
  544. daa
  545. mov m,a ; update next digit
  546. cmp e ; check for one minute
  547. rc ; return if less than limit
  548. mvi m,0 ; zero digit
  549. ret
  550. endif ; end of tod functions
  551. endif ; end of interrupts
  552. if mpmbdoscalls ; check for mp/m bdos function calls
  553. bdospatch: ; de = parameter
  554. cpi 29h ; number of normal cp/m bdos functions
  555. jc bdosfunc
  556. cpi returnserial ; check for mp/m return serial number function
  557. jrz returnserialnumber
  558. if (not todfunctions)
  559. ret ; return to bdos
  560. else ; else, check for tod bdos functions
  561. lxi h,tod ; hl := tod address, de = parameter
  562. cpi readtime ; check for mp/m read time function
  563. jrz copy4
  564. cpi readclock ; check for mp/m read clock function
  565. jrz copy5
  566. cpi settime ; check for mp/m set time function
  567. rnz ; exit if invalid function
  568. sub a ; a := 0
  569. sta todseconds ; clear seconds
  570. xchg ; hl := source of time, de := tod
  571. copy4: lxi b,4 ; move in new tod
  572. ldir
  573. ret
  574. copy5: lxi b,5 ; copy 5 bytes
  575. ldir
  576. ret
  577. endif ; end of mp/m time-of-day bdos functions
  578. returnserialnumber: ; de = user destination
  579. lxi h,bdosb ; hl := source of serial number
  580. lxi b,6 ; 6 bytes in serial number
  581. ldir ; copy to user buffer
  582. ret ; all done
  583. endif
  584. ;
  585. ;
  586. ; --- Rest of ccppatches --------------------------------
  587. ;
  588. ;
  589. continue$ccp$patch: ; fcb disk drive just tested for 0
  590. lda ccp$sdisk ; a := current drive number
  591. ora a ; zero means default was taken
  592. if scanuser0
  593. jrnz try$user0 ; try user 0 on ipl disk
  594. else
  595. jnz ccp$userer ; If nonzero, don't change it
  596. endif
  597. lda cdisk ; a := current disk/user number
  598. ani 0fh ; a := current disk
  599. mov b,a ; save current disk number
  600. lda ipldsk ; Get IPL drive
  601. cmp b ; compare ipl disk with current disk
  602. if scanuser0
  603. jrz try$user0 ; try user 0 of ipl already selected
  604. else
  605. jz ccp$userer ; error if already ipl disk and user 0
  606. endif
  607. inr a ; convert to base 1
  608. sta ccp$sdisk ; update fcb disk number with ipl disk
  609. ccp$restart:
  610. lxi d,ccp$com$fcb+9 ; Setup for retry
  611. jmp ccp$start$com ; Go do it
  612. ;
  613. ;
  614. if scanuser0 ; scan ipl drive, user 0 if .com file
  615. ; not found on designated drive
  616. ccp$local$user: db 0 ; local user number
  617. ;
  618. ccp$jnz$user0$patch:
  619. call ccp$get$user ; a := local user number
  620. sta ccp$local$user ; save, restored by load1 or userer
  621. jmp ccp$user0 ; continue in the normal fashion
  622. ;
  623. ccp$load1$patch:
  624. push psw ; save load result
  625. call ccp$reset$user ; reset to original user code
  626. pop psw
  627. jmp ccp$load1 ; continue ccp load
  628. ;
  629. ccp$userer$patch:
  630. call ccp$reset$user ; reset to original user code
  631. jmp ccp$userer ; continue with the normal error code
  632. ;
  633. ccp$reset$user:
  634. lda ccp$local$user ; a := user number
  635. mov e,a ; e := user number
  636. jmp ccp$set$user ; set user number
  637. ;
  638. ;
  639. ; --- Alternatives to default disk -------------------------
  640. ;
  641. try$user0:
  642. call ccp$get$user ; a := user code
  643. ora a
  644. jrz ccp$userer$patch ; error if user 0 already selected
  645. mvi e,0 ; e := user code
  646. call ccp$set$user ; set user 0
  647. jmpr ccp$restart
  648. ;
  649. endif ; end of scan user 0 option
  650. ;
  651. ;
  652. ; --- Additional area for XUB patch -------------------------
  653. ;
  654. ccppat3: ; select drive to delete $$$.sub
  655. lda ipldsk ; get ipl drive
  656. mov e,a
  657. mvi c,14 ; bdos select disk function code
  658. jmp bdos ; select the disk
  659. ;
  660. ;
  661. ; --- Video clock display routines -------------------------
  662. ;
  663. if displayclock
  664. videodisplaytod equ 3000h+(24*160)+(2*clockcolumn) ; line 24
  665. displaytod:
  666. lda cpm$video ; select video ram
  667. out io$sys
  668. lxi h,videodisplaytod ; hl := video display index
  669. lxi d,todhours ; de := tod index
  670. if displayampm
  671. mvi c,'A' ; c := AM/PM selection (AM default)
  672. ldax d ; a := hours (BCD)
  673. ora a ; check if hours = 0
  674. jrnz notmidnight
  675. mvi a,12h ; set to midnight (2400 hours)
  676. jmpr displayam ; it is 12 AM in the morning
  677. notmidnight:
  678. cpi 12h ; see if it is AM
  679. jrc displayam ; skip if in the morning
  680. jrz displaypm ; skip if noon
  681. adi 88h ; adjust hours (subtract 12)
  682. daa ; adjust for BCD, now 1 to 11
  683. displaypm:
  684. mvi c,'P' ; c := PM selected
  685. displayam:
  686. endif
  687. call display2a ; display hours
  688. call displaydot2 ; display minutes
  689. call displaydot2 ; display seconds
  690. if displayampm
  691. inx h ; add a space
  692. inx h ; two bytes per character
  693. mov a,c ; a := 'A' or 'P'
  694. call displaychar ; display it
  695. mvi a,'M' ; a := 'M'
  696. call displaychar ; display it too
  697. endif
  698. lda sys$current ; select previous value
  699. out io$sys
  700. ret
  701. displaydot2: ; display .dd
  702. call displaydot ; display a dot
  703. display2:
  704. ldax d ; a := 2 bcd digits
  705. display2a:
  706. push psw ; save for later
  707. rar
  708. rar
  709. rar
  710. rar ; a := ms digit
  711. call displaydigit
  712. pop psw ; a := 2 bcd digits
  713. call displaydigit
  714. inx d ; index next tod position
  715. ret
  716. displaydigit: ; display a digit
  717. ani 0fh
  718. ori '0'
  719. jmpr displaychar
  720. displaydot:
  721. mvi a,'.'
  722. displaychar:
  723. mvi m,clockattribute ; display attribute
  724. inx h
  725. mov m,a ; display character
  726. inx h
  727. ret
  728. endif
  729. ;
  730. ;
  731. ;
  732. ;Warm-boot entry point must re-load CCP and BDOS,
  733. ;then jump into CCP warm entry point.
  734. ;
  735. wboot: lxi sp,0100h ; use temporary stack for warm boot
  736. call wb$disk ; a := warm boot disk drive number
  737. lxi h,ccp+3 ; where to go on init
  738. gocpm: ; ccp and bdos loaded
  739. push h ; save ccp entry address
  740. ;
  741. mvi a,montime ; a := floppy disk motor timeout delay
  742. sta timecntr ; enable floppy disk motor timeout
  743. ;
  744. xra a ;0 to accumulator
  745. sta hstact ;host buffer inactive
  746. sta unacnt ;clear unalloc count
  747. ;
  748. mvi a,0c3h ;c3 is a jmp instruction
  749. sta 0 ;for jmp to wboot
  750. lxi h,wboote ;wboot entry point
  751. shld 1 ;set address field for jmp at 0
  752. ;
  753. sta 5 ;for jmp to bdos
  754. lxi h,bdos ;bdos entry point
  755. shld 6 ;address field of jump at 5 to bdos
  756. ;
  757. lxi b,80h ;default dma address is 80h
  758. call setdma
  759. ;
  760. lxi h,hstbuf ;set host buffer address
  761. shld bufptr ;for deblocking reads and writes
  762. ;
  763. lxi h,uktbl ;reset function key pointer
  764. shld ukptr ;to built-in translate table
  765. ;
  766. lda iobyte ;is this 40-col screen
  767. ani 3
  768. cpi 1 ;if so then modify DIR command for 2 cols.
  769. jrnz go2
  770. sta ccp+4b2h
  771. go2:
  772. if interrupts
  773. ei ;enable the interrupt system
  774. endif
  775. lda cdisk ;get current disk number
  776. mov c,a ;send to the ccp
  777. ret ;go to cp/m for further processing
  778. ;
  779. wb$disk:
  780. if memorydisk
  781. lxi h,4000h+100h ; hl := base of ccp/bdos in mdisk
  782. lxi d,ccp ; de := ccp/bdos base
  783. lxi b,bios-ccp ; number of bytes to move
  784. mvi a,mdisk$base ; a := mapping value
  785. out io$pmapa ; select mdisk base
  786. ldir ; copy ccp and bdos
  787. lda pmapa$current ; select current value
  788. out io$pmapa ; select normal ram
  789. ret
  790. else
  791. lda ipldsk ; a := physical disk number
  792. ani 0fh ; make sure it there are only 16 devices
  793. mov e,a
  794. mvi d,0 ; de := logical disk number
  795. lxi h,logical$disk ; hl := logical disk table
  796. dad d ; hl := physical disk number index
  797. mov a,m ; a := physical disk number
  798. sta hstdsk ;select boot drive
  799. lxi h,0
  800. shld hsttrk ;track 0
  801. mvi a,1 ;sector 2
  802. lxi h,ccp ;load ccp first
  803. wbloop: sta hstsec ;sector to read
  804. shld bufptr ;where to read it to
  805. call readhst ;perform read
  806. lda erflag ;was it successful?
  807. ora a
  808. jnz wboot ;retry boot on any read error
  809. lhld bufptr
  810. inr h ;bump pointer
  811. mov a,h
  812. cpi bios/256 ;done yet?
  813. rnc ;exit if yes
  814. lda hstsec ;else bump sector
  815. inr a
  816. cpi 16 ; time for seek yet?
  817. jrc wbloop ; loop back if not
  818. mvi a,1 ; else update track
  819. sta hsttrk
  820. sub a
  821. jmpr wbloop ;continue at track 1, sector 1
  822. endif
  823. ;
  824. ;
  825. ;
  826. ;Print message at (HL) until null
  827. prmsg: mov a,m ;get char
  828. ora a ;test for 0
  829. rz
  830. push h ;save pointer
  831. mov c,a
  832. call xco ;output char.
  833. pop h
  834. inx h ;bump pointer
  835. jmpr prmsg ;loop till all done
  836. ;
  837. ;
  838. ; Console drivers for Monroe 'Monty' microcomputer
  839. ;
  840. ; Entry point for normal sequential console output.
  841. ; Character to be output is passed in C reg.
  842. ;
  843. conout: sspd spsave ; Save caller's stack and set up our own
  844. lxi sp,loclstk ; so we can safely bank out low RAM
  845. lda cpm$video ; a := select byte for video ram
  846. sta sys$current ; update current value in ram
  847. out io$sys
  848. call point ; Remove existing cursor
  849. res 7,m
  850. call crtout ; Process new character
  851. call setcur ; Turn on new cursor
  852. lda cpm$system ; a := select byte while running cpm
  853. sta sys$current ; update current value in ram
  854. out io$sys ; Switch out VRAM
  855. lspd spsave ; restore user stack pointer
  856. ret ; Bye-bye
  857. ;
  858. ; Main CRT output routine
  859. ;
  860. crtout: lded ukop ; Are we loading a function key?
  861. mov a,d
  862. ora a ; we are if pointer is nonzero
  863. jrz notuko
  864. xchg ; put pointer in HL
  865. lded ukptr ; check for overflow
  866. push h
  867. dsbc d ; get offset from start of table
  868. mov a,l ; save low ord
  869. pop h ; and restore true pointer
  870. inr a
  871. ani 07h ; is pointer to last char of this key?
  872. jrnz nukov ; jump if not
  873. mvi c,0 ; if end of key, force terminating null
  874. nukov: mov m,c ; store key
  875. inx h ; bump pointer
  876. mov a,c
  877. ora a ; is this terminating null?
  878. jrnz ukoput ; no, skip
  879. lxi h,0 ; got terminating null...turn off key load
  880. ukoput: shld ukop
  881. ret ; bye bye
  882. notuko: lda escflg ; are we in an escape sequence?
  883. ora a
  884. jnz escseq ; yes, go process escape sequence
  885. mov a,c ; a := output character
  886. cpi ' ' ; Printable?
  887. jrc notprintable ; Try non-printing control characters
  888. ;
  889. ; If here, we got a printable character (we hope)
  890. ;
  891. putchar:
  892. lda attrib ; set attribute byte
  893. mov m,a ; to current attributes
  894. inx h ; Bump past attribute byte
  895. mov m,c ; Store character on screen
  896. curfwd: lda hpos ; a := hpos
  897. inr a ; Bump horizontal position
  898. lxi h,linlen ; and check for end-of-line
  899. cmp m
  900. sta hpos ; Else set new horiz pos.
  901. rc ; And exit if no wrap needed
  902. sub a ; Force HPOS back to 0
  903. sta hpos ; hpos := 0
  904. ;
  905. ; Here to advance one line
  906. ;
  907. lfout: lda vpos ; Get current line no.
  908. inr a ; Bump it
  909. cpi 24 ; Off the end?
  910. jnc rollup ; then go scroll
  911. sta vpos ; Else save new line no.
  912. ret ; and exit
  913. ;
  914. notprintable:
  915. cpi cr ; CR?
  916. jz crout
  917. cpi lf ; LF?
  918. jrz lfout
  919. cpi esc ; escape sequence?
  920. jz gotesc
  921. cpi bs ; BS?
  922. jz bsout
  923. cpi control and 'Z' ; control-Z?
  924. jz ehome ; Clear screen
  925. cpi 0bh ; VT?
  926. jz curup ; Cursor up
  927. cpi ff ; FF?
  928. jz curfwd ; Cursor right one space
  929. cpi bell ; BELL?
  930. jz beep
  931. cpi 11h ; DC1?
  932. jz eeos ; Erase EOS
  933. cpi 1eh ; ^^?
  934. jz vhome ; Home cursor
  935. ret ; ignore undecoded characters
  936. ;
  937. ; Develop address of current screen byte
  938. ;
  939. point: lda vpos ; Use current line # to get base addr
  940. add a ; a := 2 * line index (less than 47)
  941. mov e,a
  942. mvi d,0 ; de := 2 * line index (used below too)
  943. lhld ltabptr ; hl := pointer to line address table
  944. dad d ; hl := index to line address
  945. mov a,m
  946. inx h
  947. mov h,m
  948. mov l,a ; hl := address of current line
  949. lda hpos ; a := column index
  950. add a ; a := 2 * column index (less than 161)
  951. mov e,a ; de := 2 * column index (d = 0)
  952. dad d ; hl := character index
  953. ret
  954. ;
  955. ; Turn on cursor at current screen location
  956. ;
  957. setcur: call point ; Get screen address
  958. lda l80$40 ; Which machine is this?
  959. ora a
  960. jrnz setc40 ; Branch if 40-col version
  961. mvi a,14
  962. out io$crta ; Reference hi-ord cursor loc
  963. mov a,h ; and store pointer/2 since there
  964. ani 0fh ; Keep within 4k range
  965. rar ; are two VRAM bytes per char.
  966. out io$crtd
  967. mvi a,15
  968. out io$crta ; Now do low order
  969. mov a,l
  970. rar
  971. out io$crtd
  972. ret
  973. ;
  974. ; Here's the 40-col version
  975. ;
  976. setc40: setb 7,m ; Just set inverse flag on current char
  977. ret
  978. ;
  979. ; Delete line
  980. deline: lda vpos ; What line are we on?
  981. mov e,a ; e := current line index
  982. mvi d,0 ; de := current line index
  983. mvi a,23
  984. sub e ; a := number of lines below
  985. mov b,a ; b := number of lines to roll up
  986. lhld ltabptr ; hl := line index table base
  987. dad d
  988. dad d ; hl := line index index (zero flag unchanged)
  989. ora a ; check number of lines to roll up
  990. jrnz rollx ; No, do delete
  991. sta hpos ; hpos := 0, Last line....
  992. jmp eeol ; just clear it
  993. ;
  994. ; Scroll the whole screen up one line
  995. ;
  996. rollup: lda l80$40 ; a := machine type
  997. ora a ; test for 40/80 column version
  998. jrz fast$roll ; use fast scroll in 80 column version
  999. mvi b,23 ; Get # of lines
  1000. lhld ltabptr ; Point to table of line addresses
  1001. rollx: lda linlen ; Get # of columns
  1002. add a ; a := 2 * columns/line (2 bytes/char)
  1003. mov c,a ; c := bytes/line
  1004. inx h ; adjust for DCX in loop
  1005. rollnext:
  1006. dcx h ; Point to destination line
  1007. mov e,m ; and get its address
  1008. inx h
  1009. mov d,m ; de := destination line
  1010. inx h
  1011. mov a,m ; Get source line
  1012. inx h
  1013. push h ; Remember place in line address table
  1014. mov h,m
  1015. mov l,a ; hl := source line
  1016. push b ; Remember line size
  1017. mvi b,0 ; bc := bytes/line
  1018. ldir ; Copy the line
  1019. pop b ; restore loop count and line size
  1020. pop h ; restore line pointer
  1021. djnz rollnext ; repeat for 23 lines
  1022. mov d,m ; get start of last line from table
  1023. dcx h
  1024. mov e,m ; de := start of last line
  1025. xchg ; hl := start of last line
  1026. jmpr eline ; Go clear it (bc := line size)
  1027. ;
  1028. fast$roll: ; for 80 column machine from bottom line
  1029. lxi b,2*23*80 ; bc := number bytes to scroll
  1030. lxi d,3000h ; de := destination (line 0)
  1031. lxi h,3000h+(2*80) ; hl := source (line 1)
  1032. ldir ; roll the screen
  1033. xchg ; hl := first character of last line
  1034. mvi c,2*80 ; c := number of characters to erase
  1035. jmpr eline ; clear the last line (hl = last line)
  1036. ;
  1037. ; Backspace cursor
  1038. ;
  1039. bsout: lda hpos ; Get current column
  1040. ora a ; Already 0?
  1041. rz ; then ignore
  1042. dcr a ; Else back up one
  1043. sta hpos
  1044. ret
  1045. ;
  1046. ; Make some noise in version-specific way
  1047. ;
  1048. beep: lda mem$hcol ; Turn on biz model beeper
  1049. ori 1 ; turn on OC beeper bit
  1050. out io$hcol
  1051. lxi b,6cch ; Prepare for 6 bytes to port 0CCH
  1052. lxi h,urrk ; Point to noise table for educ. model
  1053. outir ; Send noise command bytes
  1054. lxi b,0e24h ; Now kill some time
  1055. beep1: djnz beep1
  1056. dcr c
  1057. jrnz beep1
  1058. lda mem$hcol ; Turn off beeper
  1059. ani 0feh ; turn off beeper control bit on OC
  1060. out io$hcol
  1061. mvi a,9fh ; For both machines
  1062. out 0cch
  1063. ret
  1064. ;
  1065. urrk: db 8eh,04h,92h,0bfh,0dfh,0ffh
  1066. ;
  1067. ; Clear the screen and home the cursor
  1068. ;
  1069. ehome: call vhome
  1070. ;
  1071. ; Erase from current cursor to end of screen
  1072. ;
  1073. eeos: lda linlen ; 40 or 80 chars per line
  1074. add a ; convert to bytes/line
  1075. mov c,a
  1076. mvi b,23 ; do 23 lines
  1077. lxi d,48
  1078. lhld ltabptr ; Point to last line of screen
  1079. dad d
  1080. eeosnext:
  1081. dcx h ; Get line address
  1082. mov d,m
  1083. dcx h
  1084. mov e,m
  1085. xchg
  1086. lda vpos ; Have we reached current line yet?
  1087. cmp b
  1088. jrz eeol ; Then only erase from cursor posn
  1089. push b
  1090. push d ; Else erase whole line
  1091. call eline
  1092. pop h
  1093. pop b ; Restore pointer and counter
  1094. djnz eeosnext ; Repeat as long as required
  1095. ;
  1096. ; Erase from current cursor to end of line
  1097. ;
  1098. eeol: call point ; Get screen address
  1099. lda hpos
  1100. mov c,a ; Figure out how many bytes left
  1101. lda linlen ; from cursor to EOL
  1102. sub c
  1103. add a ; a := 2 * number of characters
  1104. mov c,a ; c := 2 * number of characters
  1105. eline: mvi b,0 ; Hi-ord count is 0
  1106. mov e,l
  1107. mov d,h ; Source := destination
  1108. inx d
  1109. inx d ; de := index of second character
  1110. mvi m,7 ; clear attribute byte
  1111. inx h
  1112. mvi m,' ' ; first char is a space
  1113. dcx h
  1114. dcr c ; Is that all?
  1115. dcr c
  1116. rz ; Yup, just one itty bitty character
  1117. ldir ; Else copy blank to rest of line
  1118. ret
  1119. ;
  1120. ; Insert line - Scroll from cursor to EOS down and clear cursor line.
  1121. ;
  1122. inslin: lda linlen ; Convert line length
  1123. add a ; to byte count for line move
  1124. mov c,a ; and save it
  1125. mvi b,23 ; Max # of lines to move down
  1126. lxi d,48 ; Get to end of
  1127. lhld ltabptr ; line address table
  1128. dad d
  1129. insnext:
  1130. dcx h ; point to destination line
  1131. mov d,m
  1132. dcx h ; fetch destination pointer
  1133. mov e,m
  1134. xchg ; xfer to HL in case this is last line
  1135. lda vpos ; where is cursor?
  1136. cmp b ; if this is cursor line,
  1137. jrz eline ; then we're done, so just clear it
  1138. xchg ; put dest back in DE where it belongs
  1139. push h ; save position in line table
  1140. dcx h
  1141. mov a,m ; pick up source pointer
  1142. dcx h
  1143. mov l,m
  1144. mov h,a
  1145. push b ; save line counter
  1146. mvi b,0 ; we only need char count (C)
  1147. ldir ; copy line down
  1148. pop b ; get back counter
  1149. pop h ; get back line pointer
  1150. djnz insnext ; go move next line
  1151. dcx h ; we only get here for top line
  1152. mov a,m
  1153. dcx h ; set up to clear it
  1154. mov l,m
  1155. mov h,a
  1156. jmpr eline ; go do it
  1157. ;
  1158. ; Delete character under cursor
  1159. ;
  1160. delchr: call point ; get screen address
  1161. lda hpos
  1162. add a ; get # bytes from cursor to eol
  1163. mov c,a
  1164. lda linlen
  1165. add a
  1166. sub c
  1167. mov c,a
  1168. mvi b,0
  1169. mov e,l ; copy cursorn addr to de
  1170. mov d,h
  1171. inx h ; hl --> next char pos
  1172. inx h
  1173. dcr c
  1174. dcr c ; enuf bytes to move some?
  1175. jrz delch1
  1176. ldir ; copy line left 2 bytes (1 char pos)
  1177. delch1: xchg
  1178. mvi m,7 ; make vacated position a space
  1179. inx h
  1180. mvi m,' '
  1181. ret
  1182. ;
  1183. ; Insert 1 space at cursor position
  1184. ;
  1185. inschr: lda vpos ; what line are we on?
  1186. add a
  1187. mov c,a
  1188. mvi b,0 ; BC is offset into line address table
  1189. lhld ltabptr
  1190. dad b ; get entry from table
  1191. mov e,m
  1192. inx h
  1193. mov d,m ; DE is addr of beg. of line
  1194. lda linlen
  1195. dcr a ; rightmost screen cursor address
  1196. add a
  1197. push psw ; save for later
  1198. mov l,a
  1199. mvi h,0 ; copy to HL
  1200. dad d ; gives addr of rightmost char pos
  1201. mov d,h
  1202. mov e,l
  1203. dcx h ; source is char to left of it
  1204. dcx h
  1205. lda hpos ; now get cursor posn
  1206. add a ; convert to bytes
  1207. mov c,a
  1208. pop psw ; get back bytes per line - 2
  1209. sub c ; compute move count
  1210. mov c,a
  1211. mvi b,0
  1212. jrz delch1 ; skip move if at last byte
  1213. lddr ; slide line right
  1214. jmpr delch1
  1215. ;
  1216. ; HOME the cursor to column 0, line 0
  1217. ;
  1218. vhome: sub a ; Zap out line and column
  1219. sta vpos
  1220. ;
  1221. ; Handle carriage return, cursor column 0
  1222. ;
  1223. crout: sub a ; Just clear horizontal position
  1224. sta hpos
  1225. ret
  1226. ;
  1227. ; Cursor up one line
  1228. ;
  1229. curup: lda vpos
  1230. dcr a
  1231. ora a
  1232. rm
  1233. sta vpos
  1234. ret
  1235. ;
  1236. ; Handle escape character
  1237. ;
  1238. gotesc: mvi a,1 ; Set escape flag
  1239. sta escflg
  1240. ret ; that's all
  1241. ;
  1242. ; Here to process character after escape
  1243. escseq: dcr a ; flag=1?
  1244. jnz cursph ; no, must be multi-key function
  1245. sta escflg
  1246. mov a,c ; check character after escape
  1247. cpi esc ; function key load?
  1248. jz escesc
  1249. cpi '(' ; Dim off?
  1250. jz dimoff
  1251. cpi ')' ; dim on?
  1252. jz dimon
  1253. cpi '[' ; reverse off?
  1254. jz revoff
  1255. cpi ']' ; reverse on?
  1256. jz revon
  1257. cpi '{' ; underline off?
  1258. jz undoff
  1259. cpi '}' ; underline on?
  1260. jz undon
  1261. cpi '<' ; blink off?
  1262. jz blioff
  1263. cpi '>' ; blink on?
  1264. jz blion
  1265. cpi 'E' ; Insert line?
  1266. jz inslin
  1267. cpi 'F' ; Monroe attribute control?
  1268. jz escf
  1269. cpi 'G' ; ADM-31 attribute control?
  1270. jz escg
  1271. cpi 'R' ; Delete line?
  1272. jz deline
  1273. cpi 'T' ; Erase EOL?
  1274. jz eeol
  1275. cpi 'Y' ; Erase EOS?
  1276. jz eeos
  1277. cpi '*' ; Clear screen?
  1278. jz ehome
  1279. cpi 'W' ; delete char?
  1280. jz delchr
  1281. cpi 'Q' ; insert char?
  1282. jz inschr
  1283. if etxack
  1284. cpi '+' ; Set Etx/Ack on for list device
  1285. jz etxon
  1286. cpi '-' ; Set Etx/Ack off
  1287. jz etxoff
  1288. endif
  1289. cpi '=' ; Cursor address?
  1290. rnz
  1291. mvi a,3 ; flag waiting for cursor address
  1292. escxit: sta escflg ; save flag value
  1293. ret
  1294. escesc: mvi a,6
  1295. jmpr escxit
  1296. escg: mvi a,4
  1297. jmpr escxit
  1298. escf: mvi a,5
  1299. jmpr escxit
  1300. ;
  1301. ; Process possible x coordinate
  1302. cursph: dcr a ; was flag=2?
  1303. jrnz curspv ; no, must be y coordinate
  1304. mov a,c ; get coordinate
  1305. sui 32 ; remove offset
  1306. lxi h,linlen ; point to line length
  1307. cursh1: cmp m ; make sure not out of range
  1308. jrc cursh2
  1309. sub m ; adjust and re-check
  1310. jmpr cursh1
  1311. cursh2: sta hpos ; save it
  1312. zapesc: sub a ; clear escape flag
  1313. jmpr escxit
  1314. ;
  1315. ; Process y coordinate
  1316. curspv: dcr a ; was flag=3?
  1317. jrnz escgv ; no, try attribute controls
  1318. mov a,c ; get char
  1319. ani 31 ; remove offset
  1320. cursv1: cpi 24 ; range check
  1321. jrc cursv2
  1322. sui 24
  1323. cursv2: sta vpos ; save new row number
  1324. mvi a,2 ; change flag for column
  1325. jmpr escxit
  1326. ;
  1327. ; Process ADM-31 attribute control (ESC G <0-7>)
  1328. escgv: dcr a ; was escflg=4?
  1329. jrnz escfv ; no, try Monroe attributes
  1330. mov a,c
  1331. sui '0' ; check for valid digit
  1332. jrc zapesc
  1333. cpi 8 ; must be 0-7
  1334. jrnc zapesc
  1335. mov c,a ; look up correspinding attributes
  1336. mvi b,0
  1337. lxi h,escgtbl ; in table
  1338. dad b
  1339. lda attrib ; get current attributes
  1340. ani 40h ; preserve dim attribute
  1341. ora m ; include new attributes
  1342. stazap: sta attrib ; store new attribute byte
  1343. jmpr zapesc ; and terminate escape sequence
  1344. ;
  1345. escgtbl:db 0,7,4,7,10h,17h,14h,17h
  1346. ;
  1347. ; Process Monroe attribute control (esc F <byte>)
  1348. escfv: dcr a ; was escflg = 5?
  1349. jrnz uknum ; no, try next handler
  1350. mov a,c ; this one's easy...just store
  1351. jmpr stazap ; whole byte as attributes
  1352. ;
  1353. ; Process downloaded function key number
  1354. ; (esc esc <key# + 31> <0-7 text chars> nul)
  1355. uknum: mov a,c ; get key #
  1356. ani 3FH ; restrict range
  1357. cpi 32+nfk
  1358. jrnc zapesc
  1359. mov l,a
  1360. mvi h,0
  1361. lbcd ukptr ; base of table
  1362. dad h
  1363. dad h ; offset to this key
  1364. dad h
  1365. dad b
  1366. shld ukop ; save pointer for next call
  1367. jmpr zapesc ; now turn off escflg
  1368. ;
  1369. ; Enable dim character mode
  1370. dimon: mvi c,40h ; select dim bit
  1371. ; and fall thru
  1372. ; Set an attribute bit
  1373. atton: lda attrib ; get current attribute byte
  1374. ora c ; and set appropriate bit
  1375. sta attrib
  1376. ret
  1377. ;
  1378. ; End dim character mode
  1379. dimoff: mvi c,0bfh ; select dim bit
  1380. ; and fall thru
  1381. ; Clear an attribute bit
  1382. attoff: lda attrib ; get attribute byte
  1383. ana c ; and clear appropriate bit
  1384. sta attrib
  1385. ret
  1386. ;
  1387. ; Reverse on
  1388. revon: mvi c,10h
  1389. jmpr atton
  1390. ;
  1391. ; reverse off
  1392. revoff: mvi c,0efh
  1393. jmpr attoff
  1394. ;
  1395. ; underline on
  1396. undon: mvi c,08h
  1397. jmpr atton
  1398. ;
  1399. ; underline off
  1400. undoff: mvi c,0f7h
  1401. jmpr attoff
  1402. ;
  1403. ; blink on
  1404. blion: mvi c,04h
  1405. jmpr atton
  1406. ;
  1407. ; blink off
  1408. blioff: mvi c,0fbh
  1409. jmpr attoff
  1410. ;
  1411. if etxack
  1412. ;
  1413. ; Set etx/ack flag on
  1414. etxon: mvi a,0ffh
  1415. sta enableetxack
  1416. ret
  1417. ;
  1418. ; Set etx/ack flag off
  1419. etxoff: sub a
  1420. sta enableetxack
  1421. ret
  1422. ;
  1423. endif
  1424. ;
  1425. ; Define a macro to generate table of N addresses, starting
  1426. ; with B, incrementing by L. This is what we need to build
  1427. ; line address tables for screens.
  1428. ADRTBL MACRO B,L,N
  1429. @A SET B
  1430. REPT N
  1431. DW @A
  1432. @A SET @A+L
  1433. ENDM
  1434. ENDM
  1435. ;
  1436. ; 80-Column line address table
  1437. ;
  1438. LTAB80: ADRTBL 3000H,160,24
  1439. ;
  1440. ; 40-Column line address table
  1441. ;
  1442. LTAB40: ADRTBL 3000H,100H,8
  1443. ADRTBL 3050H,100H,8
  1444. ADRTBL 30A0H,100H,8
  1445. ;
  1446. ;
  1447. lconout:
  1448. lda iobyte ; a := io byte
  1449. ani 03 ; check current assignment
  1450. cpi 02
  1451. jc conout ; TTY: or CRT:
  1452. jz llist ; BAT:
  1453. ; else must be UC1:
  1454. uc1out: sub a ; a := 0
  1455. out io$siobc ; select status register
  1456. in io$siobc ; a := status register
  1457. ani 04 ; select output status bit
  1458. jrz uc1out ; wait until ready
  1459. mov a,c ; a := output character
  1460. out io$siobd ; output character
  1461. ret
  1462. ;
  1463. ;
  1464. ; Console status routine -- returns 0FFH when char available,
  1465. ; otherwise returns 00
  1466. ;
  1467. lconst:
  1468. if (interrupts and eiconst)
  1469. ei ; enable interrupts
  1470. endif
  1471. if (not interrupts)
  1472. call chkmotor ; do floppy motor timing
  1473. endif
  1474. lda iobyte ; dispatch to current console
  1475. ani 03
  1476. cpi 02
  1477. jrc const ; builtin console
  1478. jrz lrdrst ; batch (logical RDR in, logical LST out)
  1479. uc1st: sub a ; aux port
  1480. out io$siobc
  1481. in io$siobc
  1482. jmpr genst ; rest of code is common
  1483. ;
  1484. lrdrst: lda iobyte ; get iobyte
  1485. ani 0ch ; get reader bits
  1486. jrz rdrst ; it's physical reader (COMM port)
  1487. cpi 08h ; check other possibilities
  1488. jrc const ; CRT
  1489. jrz uc1st ; AUX
  1490. lptst: sub a ; PRI
  1491. out io$drtac
  1492. in io$drtac
  1493. jmpr genst
  1494. rdrst: sub a ; COM
  1495. out io$sioac
  1496. in io$sioac
  1497. jmpr genst
  1498. ;
  1499. ; builtin console
  1500. const: lhld ukip ; function key in progress?
  1501. mov a,h
  1502. ora a
  1503. jrz const1 ; jump if not
  1504. mov a,m
  1505. ora a ; return true unless end of funct key
  1506. jrnz const2
  1507. const1:
  1508. if coninterrupt
  1509. lxi h,inputpointer ; hl := console buffer pointer index
  1510. mov a,m ; a := input pointer
  1511. inx h ; hl := output pointer index
  1512. sub m ; compare with output pointer
  1513. jrnz const2 ; return true if not equal
  1514. else
  1515. sub a ; Select DART register 0
  1516. out io$drtbc
  1517. in io$drtbc
  1518. endif
  1519. genst: ani 01h ; Check data-avail bit
  1520. rz
  1521. const2: mvi a,0ffh
  1522. ret
  1523. ;
  1524. ; Console input routine -- waits for a char and returns it
  1525. ;
  1526. lconin: call lconst ;check ready and motor timing
  1527. ora a
  1528. jrz lconin
  1529. lda iobyte ;now split to right routine
  1530. ani 03
  1531. cpi 02
  1532. jrc conin
  1533. jz lreader
  1534. call uc1in
  1535. ani 7fh
  1536. ret
  1537. ;
  1538. ;AUX port driver
  1539. uc1in: call uc1st
  1540. jrz uc1in
  1541. in io$siobd
  1542. ret
  1543. ;
  1544. ; Built-in keyboard driver
  1545. ; Note: high bit is not stripped, since it is used to
  1546. ; signify one of the special keys on the system keyboard.
  1547. conin: lhld ukip ; is function key active?
  1548. mov a,h
  1549. ora a
  1550. jrz conin1 ; no, do physical read
  1551. ukin: mov a,m ; get next byte of func key
  1552. inx h ; bump pointer
  1553. shld ukip ; save new pointer
  1554. ora a ; is this terminating null?
  1555. rnz ; return if not
  1556. lxi h,0 ; got null, turn off function key
  1557. shld ukip ; and fall into normal input
  1558. conin1: call const ; Wait for data
  1559. jrz conin1
  1560. if coninterrupt
  1561. lda outputpointer ; a := output pointer
  1562. mov l,a
  1563. mvi h,0 ; hl := output pointer
  1564. lxi d,conbuffer ; de := console buffer base
  1565. dad d ; hl := character index
  1566. mov c,m ; c := character
  1567. inr a ; increment pointer
  1568. cpi conbuffersize ; check for overflow
  1569. jrc conin1a
  1570. sub a ; a := 0 (start of buffer)
  1571. conin1a: sta outputpointer ; update output pointer
  1572. mov a,c ; get it
  1573. else
  1574. in io$drtbd ; Get it
  1575. endif
  1576. if debug
  1577. cpi 0d4h ; monitor trap?
  1578. jz 0f800h
  1579. endif
  1580. cpi 80h ; special key?
  1581. rc ; if not, return
  1582. lxi b,nfk*256+0a0h ; # of white function keys + first value
  1583. lxi h,fktbl ; table of same
  1584. fklup: cmp m ; do we have one?
  1585. jrz gotfk ; jump if match
  1586. inr c
  1587. inx h ; point to next key
  1588. djnz fklup ; loop till out of keys
  1589. mov c,a ; use original key
  1590. gotfk: mov a,c ; replace key with translated value
  1591. cpi 0a0h+nfk
  1592. rnc ; return if too big *** can't happen ***
  1593. ani 3fh ; get table offset
  1594. mov l,a
  1595. mvi h,0
  1596. lbcd ukptr ; make pointer into user key table
  1597. dad h
  1598. dad h
  1599. dad h
  1600. dad b
  1601. jmpr ukin ; now fetch from table
  1602. ;
  1603. ; "Hardwired" function key table (white keys)
  1604. FKTBL: DB 0CAH ; insrt lock
  1605. DB 0C1H ; char del
  1606. DB 0D0H ; run
  1607. DB 0C0H ; print scrn
  1608. DB 0D4H ; calc mode
  1609. DB 0C7H ; home
  1610. DB 0C5H ; up arrow
  1611. DB 0C6H ; down arrow
  1612. DB 0C4H ; right arrow
  1613. DB 0C3H ; left arrow
  1614. DB 0C2H ; line del
  1615. DB 0D1H ; load
  1616. DB 0D2H ; cont
  1617. DB 0D3H ; shft calc mode
  1618. DB 0C8H ; clear
  1619. DB 0B5H ; cntl up arrow
  1620. DB 0B6H ; cntl down arrow
  1621. DB 0B4H ; cntl right arrow
  1622. DB 0B3H ; cntl left arrow
  1623. DB 0FFH ; stop
  1624. DB 0A8H ; cntl backspace
  1625. DB 0A9H ; cntl tab
  1626. NFK EQU $-FKTBL
  1627. ;
  1628. ;
  1629. ;List device drivers
  1630. llist: lda lstsec ; a := list time-out in seconds |14|
  1631. sta lstcnt ; update list time-out counter |14|
  1632. call llistwait
  1633. lda iobyte ; dispatch to correct driver
  1634. ani 0c0h ; get list field
  1635. jrz list ; default (TTY:)
  1636. cpi 80h
  1637. jc conout ; CRT:
  1638. jz punch ; LPT: (comm port)
  1639. jmp uc1out ; UC1: (aux port)
  1640. ;
  1641. llistwait:
  1642. call llistst ; a := llist status
  1643. ora a ; ready?
  1644. rnz ; exit when ready?
  1645. lda lstcnt ; a := list time-out counter
  1646. ora a ; time-out?
  1647. jrnz llistwait ; loop until time-out or ready
  1648. lxi h,lstmsg ; hl := print not ready message
  1649. call prmsg ; print message
  1650. llistlp:
  1651. call llistst ; a := llist status
  1652. ora a ; ready?
  1653. jnz crlf ; terminate message and exit
  1654. call xconst ; a := console status
  1655. ora a ; character ready?
  1656. jrz llistlp ; loop until ready or character entered
  1657. call xconin ; a := console character
  1658. cpi 3 ; control-c?
  1659. jrnz llistlp ; loop if not control-c
  1660. jmp wboot ; abort program
  1661. ;
  1662. lstmsg: db 7,13,10,'Printer not ready',0
  1663. ;
  1664. ;
  1665. ; Printer port driver
  1666. ;
  1667. ; For etx/ack protocol, if an ESC char is found when the length
  1668. ; of the current output line is between llimit and ulimit, an Etx
  1669. ; char is sent before sending the ESC char. Also when the length
  1670. ; reaches the ulimit, Etx is sent.
  1671. ;
  1672. list:
  1673. call listst ; check status
  1674. jrz list ; wait until printer ready
  1675. if etxack
  1676. lda enableetxack ; check if etxack flag is set or not
  1677. ora a ; 0 means not set
  1678. jrz list2
  1679. lda lsize ; a := current line size
  1680. inr a ; increment size
  1681. sta lsize ; save size
  1682. cpi llimit ; compare to lower limit
  1683. jrc list2 ; send character if under lower limit
  1684. cpi ulimit ; compare to upper limit
  1685. jrnc sendetx ; send etx if over limit
  1686. mov a,c ; a := character to be printed
  1687. cpi esc ; Check for escape sequence
  1688. jrz sendetx ; send etx if escape sequence
  1689. list2:
  1690. endif
  1691. mov a,c ; a := character to send to printer
  1692. out io$drtad ; send character to printer
  1693. ret ; exit
  1694. if etxack
  1695. sendetx: ; send an etx character
  1696. sub a ; a := 0
  1697. sta lsize ; current line size := 0
  1698. sta enablelist ; disable listing
  1699. mvi a,etx
  1700. out io$drtad ; output to printer
  1701. jmpr list ; try again
  1702. endif
  1703. ;
  1704. ;
  1705. ; List device status returns a=0 if not ready, a=ff if ready
  1706. llistst:
  1707. lda iobyte ; a := io byte
  1708. ani 0c0h
  1709. jrz listst
  1710. cpi 80h
  1711. jrz punst
  1712. jrc conost
  1713. uc1ost: sub a ; a := 0
  1714. out io$siobc ; select status register
  1715. in io$siobc ; a := io status byte
  1716. jmpr genost ; return output status
  1717. punst: sub a ; a := 0
  1718. out io$sioac ; select status register
  1719. in io$sioac ; a := io status
  1720. jmpr genost ; return output status
  1721. conost: mvi a,0ffh ; return all ones
  1722. ret
  1723. ;
  1724. ; Normal printer port status
  1725. enablelist: db 0ffh ; initially enabled
  1726. listst: sub a ; a := 0
  1727. out io$drtac ; select status port
  1728. in io$drtac ; a := list status
  1729. ani 01h ; get input status
  1730. jrz list1
  1731. in io$drtad ; a := input character
  1732. ani 07fh ; get an ASCII character
  1733. cpi xon ; check for an xon
  1734. jrz listxon
  1735. cpi xoff ; check for an xoff
  1736. jrz listxoff
  1737. if etxack
  1738. cpi ack ; check for an ack
  1739. jrz listxon
  1740. endif
  1741. list1: lda enablelist ; check if an xoff has disabled the list device
  1742. ora a
  1743. rz ; return zero if not ready (due to xoff)
  1744. SUB A ; a := 0
  1745. OUT IO$DRTAC ; select status port
  1746. IN IO$DRTAC ; a := list status
  1747. genost: ANI 04h
  1748. rz ; return zero if not ready
  1749. mvi a,0ffh ; return 0ffh (true) if ready
  1750. ret
  1751. listxoff:
  1752. sub a ; a := 0
  1753. sta enablelist ; turn off the list device
  1754. jmpr listst ; check again
  1755. listxon:
  1756. mvi a,0ffh ; a := 0ffh
  1757. sta enablelist ; turn on the list device
  1758. jmpr listst
  1759. ;
  1760. lpunch: ;punch character from register c
  1761. lda iobyte ; a := io byte
  1762. ani 30h ; see if punch selected
  1763. jrz punch
  1764. cpi 20h ; see if console selected
  1765. jc conout ; console if less than 20h
  1766. jz uc1out ; aux: if equal to 20h
  1767. jmp list ; must be list device
  1768. ;
  1769. ; comm port output
  1770. punch: sub a ; a := 0
  1771. out io$sioac ; select status port
  1772. in io$sioac ; a := com: port status
  1773. ani 4 ; check input status bit
  1774. jrz punch ; wait until ready
  1775. mov a,c ; a := outuput character
  1776. out io$sioad ; output character
  1777. ret ; exit
  1778. ;
  1779. ;
  1780. lreader: ;read character into register a from reader device
  1781. lda iobyte ; a := io byte
  1782. ani 0ch ; get lower bits
  1783. jrz reader ; check for physical device
  1784. cpi 08h
  1785. jc conin
  1786. jz uc1in
  1787. lptin: call lptst ; wait until ready
  1788. jrz lptin
  1789. in io$drtad ; output character
  1790. ret
  1791. ;
  1792. reader: call rdrst ; wait for reader to become ready
  1793. jrz reader
  1794. in io$sioad ; output character
  1795. ret
  1796. ;
  1797. ;
  1798. ;*****************************************************
  1799. ;* *
  1800. ;* Sector Deblocking Algorithms for CP/M 2.2 *
  1801. ;* *
  1802. ;*****************************************************
  1803. ;
  1804. ; utility macro to compute sector mask
  1805. smask macro hblk
  1806. ;; compute log2(hblk), return @x as result
  1807. ;; (2 ** @x = hblk on return)
  1808. @y set hblk
  1809. @x set 0
  1810. ;; count right shifts of @y until = 1
  1811. rept 8
  1812. if @y = 1
  1813. exitm
  1814. endif
  1815. ;; @y is not 1, shift right one position
  1816. @y set @y shr 1
  1817. @x set @x + 1
  1818. endm
  1819. endm
  1820. ;
  1821. ;*****************************************************
  1822. ;* *
  1823. ;* CP/M to host (Monty) disk constants *
  1824. ;* *
  1825. ;*****************************************************
  1826. blksiz equ 2048 ;CP/M allocation size
  1827. hstsiz equ 256 ;host disk sector size
  1828. hstspt equ 16 ;host disk sectors/trk
  1829. hstblk equ hstsiz/128 ;CP/M sects/host buff
  1830. cpmspt equ hstblk * hstspt ;CP/M sectors/track
  1831. secmsk equ hstblk-1 ;sector mask
  1832. smask hstblk ;compute sector mask
  1833. secshf equ @x ;log2(hstblk)
  1834. ;
  1835. ;*****************************************************
  1836. ;* *
  1837. ;* BDOS constants on entry to write *
  1838. ;* *
  1839. ;*****************************************************
  1840. wrall equ 0 ;write to allocated
  1841. wrdir equ 1 ;write to directory
  1842. wrual equ 2 ;write to unallocated
  1843. ;
  1844. ;*****************************************************
  1845. ;* *
  1846. ;* Disk parameter blocks for drives: *
  1847. ;* *
  1848. ;*****************************************************
  1849. ;
  1850. logical$size: ; CP/M records/block (see diskdef)
  1851. rept 4 ; floppy disks (4)
  1852. db 16 ; 16 records (2048 bytes)/block
  1853. endm
  1854. rept 4 ; hard disks (4)
  1855. db 16 ; 16 records (2048 bytes)/block
  1856. endm
  1857. rept 1 ; memory disk (1)
  1858. db 8 ; 8 records (1024 bytes)/block
  1859. endm
  1860. rept 7 ; remaining logical disks (7)
  1861. db 0 ; not used
  1862. endm
  1863. ;
  1864. ;
  1865. disks maxdisk ; CP/M disk parameter blocks
  1866. ;
  1867. ; Floppy disk constants
  1868. ;
  1869. diskdef 0,1,32,,2048,154,64,64,3
  1870. diskdef 1,0
  1871. diskdef 2,0
  1872. diskdef 3,0
  1873. ;
  1874. ; Hard disk constants
  1875. ; size is (19200/8)-(48/8)=2394 useable blks |10|
  1876. ;
  1877. diskdef 4,0,31,,2048,2394,512,0,3
  1878. diskdef 5,4
  1879. diskdef 6,4
  1880. diskdef 7,4
  1881. ;
  1882. ; Memory disk constants. 'mdisk$dsm' is the address of the word which
  1883. ; indicates the number of block (1K bytes/block in this case) less one.
  1884. ; It should have a value of 64 in a 128K system and 180 in a 256K system.
  1885. ; The 'mdisk$off' is the address of the word which indicates the number
  1886. ; of offset tracks which should be used. It is 0 for a 128K system and
  1887. ; 1 for a 256K system.
  1888. ;
  1889. if memorydisk
  1890. mdisk$dsm equ $+5 ; |2.27.01|
  1891. diskdef 8,0,63,,1024,180,32,0,1 ; |2.27.01|
  1892. clearmemorydisk equ 16 ; number of 128 byte sectors to set to E5h
  1893. ; should be number of directory entries/4
  1894. endif
  1895. ;
  1896. ;
  1897. ;home the selected disk
  1898. home:
  1899. lda hstwrt ;check for pending write
  1900. ora a
  1901. jrnz homed
  1902. sta hstact ;clear host active flag
  1903. homed:
  1904. lxi h,0
  1905. shld sektrk
  1906. ret
  1907. ;
  1908. seldsk: ;select disk
  1909. mov a,c ;selected disk number
  1910. ani 0fh ; make sure it there are only 16 devices
  1911. mov e,a
  1912. mvi d,0 ; de := logical disk number
  1913. lxi h,logical$size ; hl := logical disk block size table
  1914. dad d ; hl := table index
  1915. mov a,m ; a := logical (128 byte) records per block
  1916. sta records$per$block
  1917. lxi h,logical$disk ; hl := logical disk table
  1918. dad d ; hl := physical disk number index
  1919. mov a,m ; a := physical disk number
  1920. sta sekdsk ;seek disk number
  1921. lxi h,0
  1922. cpi maxdisk ;trap bad drive #
  1923. rnc
  1924. mov l,a ;disk number to HL
  1925. rept 4 ;multiply by 16
  1926. dad h
  1927. endm
  1928. lxi d,dpbase ;base of parm block
  1929. dad d ;hl=.dpb(curdsk)
  1930. ret
  1931. ;
  1932. settrk:
  1933. ;set track given by registers BC
  1934. sbcd sektrk ;track to seek
  1935. ret
  1936. ;
  1937. setsec:
  1938. ;set sector given by register c
  1939. mov a,c
  1940. sta lac$sec ;sector to seek (with interlace applied)
  1941. ret
  1942. ;
  1943. setdma:
  1944. ;set dma address given by BC
  1945. sbcd dmaadr
  1946. ret
  1947. ;
  1948. sectran:
  1949. ;translate sector number BC
  1950. mov a,c
  1951. sta sek$sec ;save un-interlaced sector for deblock logic
  1952. LDA sekdsk ;check for hard disk
  1953. CPI 4
  1954. JRC INTLC
  1955. MOV L,C
  1956. MVI H,0
  1957. RET ;NO INTERLACE FOR HARD DISK
  1958. ;
  1959. INTLC: lxi h,xltbl
  1960. dad b ;look up interlaced sector
  1961. mov l,m
  1962. mvi h,0
  1963. ret
  1964. ;
  1965. ;*****************************************************
  1966. ;* *
  1967. ;* The READ entry point performs a 'logical' *
  1968. ;* 128-byte read with deblocking. *
  1969. ;* *
  1970. ;*****************************************************
  1971. read:
  1972. ;read the selected CP/M sector
  1973. if memorydisk
  1974. lda sekdsk ; a := select disk number
  1975. cpi mdrive ; |10|
  1976. jz memoryread ; and see if it is the memory drive |10|
  1977. endif
  1978. mvi a,1
  1979. sta readop ;read operation
  1980. sta rsflag ;must read data
  1981. xra a ; a := 0
  1982. sta unacnt
  1983. mvi a,wrual
  1984. sta wrtype ;treat as unalloc
  1985. jmpr rwoper ;to perform the read
  1986. ;
  1987. ;*****************************************************
  1988. ;* *
  1989. ;* The WRITE entry point does a 'logical' *
  1990. ;* 128-byte write with blocking. *
  1991. ;* *
  1992. ;*****************************************************
  1993. write:
  1994. ;write the selected CP/M sector
  1995. if memorydisk
  1996. lda sekdsk ; a := select disk number
  1997. cpi mdrive ; |10|
  1998. jz memorywrite ; and see if it is the memory drive |10|
  1999. endif
  2000. xra a ;0 to accumulator
  2001. sta readop ;not a read operation
  2002. mov a,c ;write type in c
  2003. sta wrtype
  2004. cpi wrual ;write unallocated?
  2005. jrnz chkuna ;check for unalloc
  2006. ;
  2007. ; write to unallocated, set parameters
  2008. lda records$per$block ;next unalloc recs
  2009. sta unacnt
  2010. lda sekdsk ;disk to seek
  2011. sta unadsk ;unadsk = sekdsk
  2012. lhld sektrk
  2013. shld unatrk ;unatrk = sectrk
  2014. lda seksec
  2015. sta unasec ;unasec = seksec
  2016. ;
  2017. chkuna:
  2018. ;check for write to unallocated sector
  2019. lda unacnt ;any unalloc remain?
  2020. ora a
  2021. jrz alloc ;skip if not
  2022. ;
  2023. ; more unallocated records remain
  2024. dcr a ;unacnt = unacnt-1
  2025. sta unacnt
  2026. lda sekdsk ;same disk?
  2027. lxi h,unadsk
  2028. cmp m ;sekdsk = unadsk?
  2029. jrnz alloc ;skip if not
  2030. ;
  2031. ; disks are the same
  2032. lxi h,unatrk
  2033. call sektrkcmp ;sektrk = unatrk?
  2034. jrnz alloc ;skip if not
  2035. ;
  2036. ; tracks are the same
  2037. lda seksec ;same sector?
  2038. lxi h,unasec
  2039. cmp m ;seksec = unasec?
  2040. jrnz alloc ;skip if not
  2041. ;
  2042. ; match, move to next sector for future ref
  2043. inr m ;unasec = unasec+1
  2044. mov a,m ;end of track?
  2045. cpi cpmspt ;count CP/M sectors
  2046. jrc noovf ;skip if no overflow
  2047. ;
  2048. ; overflow to next track
  2049. mvi m,0 ;unasec = 0
  2050. lhld unatrk
  2051. inx h
  2052. shld unatrk ;unatrk = unatrk+1
  2053. ;
  2054. noovf:
  2055. ;match found, mark as unnecessary read
  2056. xra a ;0 to accumulator
  2057. sta rsflag ;rsflag = 0
  2058. jmpr rwoper ;to perform the write
  2059. ;
  2060. alloc:
  2061. ;not an unallocated record, requires pre-read
  2062. xra a ;0 to accum
  2063. sta unacnt ;unacnt = 0
  2064. inr a ;1 to accum
  2065. sta rsflag ;rsflag = 1
  2066. ;
  2067. ;*****************************************************
  2068. ;* *
  2069. ;* Common code for READ and WRITE follows *
  2070. ;* *
  2071. ;*****************************************************
  2072. rwoper:
  2073. ;enter here to perform the read/write
  2074. xra a ;zero to accum
  2075. sta erflag ;no errors (yet)
  2076. lda lac$sec ;compute host sector
  2077. rept secshf
  2078. ora a ;carry = 0
  2079. rar ;shift right
  2080. endm
  2081. sta sekhst ;host sector to seek
  2082. ;
  2083. ; active host sector?
  2084. lxi h,hstact ;host active flag
  2085. mov a,m
  2086. mvi m,1 ;always becomes 1
  2087. ora a ;was it already?
  2088. jrz filhst ;fill host if not
  2089. ;
  2090. ; host buffer active, same as seek buffer?
  2091. lda sekdsk
  2092. lxi h,hstdsk ;same disk?
  2093. cmp m ;sekdsk = hstdsk?
  2094. jrnz nomatch
  2095. ;
  2096. ; same disk, same track?
  2097. lxi h,hsttrk
  2098. call sektrkcmp ;sektrk = hsttrk?
  2099. jrnz nomatch
  2100. ;
  2101. ; same disk, same track, same buffer?
  2102. lda sekhst
  2103. lxi h,hstsec ;sekhst = hstsec?
  2104. cmp m
  2105. jrz match ;skip if match
  2106. ;
  2107. nomatch: ;proper disk, but not correct sector
  2108. call checkwritehst ; check if host buffers needs to be written
  2109. ;
  2110. filhst: ;may have to fill the host buffer
  2111. lda sekdsk
  2112. sta hstdsk
  2113. lhld sektrk
  2114. shld hsttrk
  2115. lda sekhst
  2116. sta hstsec
  2117. lda rsflag ;need to read?
  2118. ora a
  2119. cnz readhst ;yes, if 1
  2120. xra a ;0 to accum
  2121. sta hstwrt ;no pending write
  2122. ;
  2123. match:
  2124. ;copy data to or from buffer
  2125. lda lac$sec ;mask buffer number
  2126. ani secmsk ;least signif bits
  2127. mov l,a ;ready to shift
  2128. mvi h,0 ;double count
  2129. rept 7 ;shift left 7
  2130. dad h
  2131. endm
  2132. ; hl has relative host buffer address
  2133. lxi d,hstbuf
  2134. dad d ;hl = host address
  2135. lded dmaadr ;get/put CP/M data
  2136. lxi b,128 ;length of move
  2137. lda readop ;which way?
  2138. ora a
  2139. jrnz rwmove ;skip if read
  2140. ;
  2141. ; write operation, mark and switch direction
  2142. mvi a,1
  2143. sta hstwrt ;hstwrt = 1
  2144. xchg ;source/dest swap
  2145. ;
  2146. rwmove:
  2147. ;BC initially 128, HL is source, DE is dest
  2148. ldir
  2149. ;
  2150. ; data has been moved to/from host buffer
  2151. lda wrtype ;write type
  2152. cpi wrdir ;to directory?
  2153. lda erflag ;in case of errors
  2154. rnz ;no further processing
  2155. ;
  2156. ; clear host buffer for directory write
  2157. ora a ;errors?
  2158. rnz ;skip if so
  2159. xra a ;0 to accum
  2160. sta hstwrt ;buffer written
  2161. call writehst ; write buffer
  2162. lda erflag ; a := result (error flag)
  2163. ret
  2164. ;
  2165. ;*****************************************************
  2166. ;* *
  2167. ;* Utility subroutine for 16-bit compare *
  2168. ;* *
  2169. ;*****************************************************
  2170. sektrkcmp:
  2171. ;HL = .unatrk or .hsttrk, compare with sektrk
  2172. xchg
  2173. lxi h,sektrk
  2174. ldax d ;low byte compare
  2175. cmp m ;same?
  2176. rnz ;return if not
  2177. ; low bytes equal, test high 1s
  2178. inx d
  2179. inx h
  2180. ldax d
  2181. cmp m ;sets flags
  2182. ret
  2183. ;
  2184. ;*****************************************************
  2185. ;* *
  2186. ;* WRITEHST performs the physical write to *
  2187. ;* the host disk, READHST reads the physical *
  2188. ;* disk. *
  2189. ;* *
  2190. ;*****************************************************
  2191. dma$read equ 7dh
  2192. dma$write equ 79h
  2193. ;
  2194. ;
  2195. checkwritehst:
  2196. lda hstwrt ;host written?
  2197. ora a
  2198. rz ; exit if host written
  2199. writehst:
  2200. ;hstdsk = host disk #, hsttrk = host track #,
  2201. ;hstsec = host sect #. write "hstsiz" bytes
  2202. ;from hstbuf and return error flag in erflag.
  2203. ;return erflag non-zero if error
  2204. ;
  2205. lxi b,(fcwri� shl 8)+wrsec � se� fd� command in b and XBC in C |10|
  2206. lxi h,(dma$write shl 8)+05 ; DMA command and direction |10|
  2207. jmpr rwhst ; go to common code
  2208. ;
  2209. readhst:
  2210. ;hstdsk = host disk #, hsttrk = host track #,
  2211. ;hstsec = host sect #. read "hstsiz" bytes
  2212. ;into hstbuf and return error flag in erflag.
  2213. ;
  2214. lxi b,(fcread shl 8)+rdsec ; set fdc command in b and XBC in c |10|
  2215. lxi h,(dma$read shl 8)+01 ; DMA command and direction |10|
  2216. ; and fall thru to common code
  2217. ;
  2218. ;***************************************************
  2219. ;* *
  2220. ;* Common code for physical read/write *
  2221. ;* *
  2222. ;***************************************************
  2223. ;
  2224. rwhst:
  2225. shld dmarw ;save the dma controller command |10|
  2226. lda hstdsk ;look up the requested drive
  2227. cpi maxfloppy
  2228. jnc hdrw ;go to the hard disk driver
  2229. ;
  2230. ;this is the floppy driver
  2231. ;
  2232. if interrupts
  2233. ei ; turn on timer interrupt just in case
  2234. endif
  2235. LXI H,fpycmd
  2236. MOV M,B
  2237. mov c,a ;for this drive
  2238. mvi b,0
  2239. lxi h,trktbl
  2240. dad b
  2241. mov a,m
  2242. out io$fdtrk ;pass it to fdc
  2243. mov b,c
  2244. inr b ;generate shift count
  2245. sub a
  2246. sta timecntr ;disable motor timeout
  2247. stc
  2248. nrbit: ;generate drive select bit
  2249. adc a
  2250. djnz nrbit
  2251. mov e,a ;save select mask
  2252. call motoron ;turn on motors
  2253. jrnz wason ;skip delay if already on
  2254. mvi c,0
  2255. mondly:
  2256. xthl ;kill lots of time
  2257. xthl
  2258. xthl
  2259. xthl
  2260. djnz mondly
  2261. dcr c
  2262. jrnz mondly
  2263. wason:
  2264. in io$fdst ;see if drive is alive
  2265. ani fsnrdy
  2266. jrz fpy$seek ;skip if ready
  2267. call drvnrdy ;else wait for user to fix it
  2268. jmpr mondly-2 ;and give it some time to sync up
  2269. fpy$seek:
  2270. mvi a,maxrtr ;set retry count
  2271. sta fpyrtry
  2272. fpy$rsek:
  2273. lda hstsec ;set desired sector
  2274. inr a ;change 0-15 into 1-16
  2275. out io$fdsec
  2276. lda hsttrk ;set track for seek operation
  2277. ora a ;track 0?
  2278. jrnz doseek ;skip if not
  2279. call restore ;turn seek 0 into restore
  2280. sub a
  2281. doseek:
  2282. lbcd hstdsk ;index into track table
  2283. mvi b,0
  2284. lxi h,trktbl
  2285. dad b
  2286. cmp m ;compare to desired track
  2287. jrz noseek ;skip seek if already there
  2288. inr m ;255 means drive never accessed
  2289. cz restore ;do restore if first access to drive
  2290. lda hsttrk
  2291. out io$fdata ;set track # for seek
  2292. mov m,a ;store new track # in table
  2293. cpi 52 ;time for precompensation?
  2294. lda fpyctrl
  2295. jrc noprec ;adjust command accordingly
  2296. ori fdprec
  2297. noprec:
  2298. call newctrl ;send new control port bits
  2299. mvi a,fcseek+fcverf+rate ;do seek with verify
  2300. call xqt
  2301. in io$fdst ;check status
  2302. ani fscrc+fsrnf+fsnrdy ;check for errors
  2303. jrz noseek
  2304. call resterr ;if error, home and retry
  2305. lda fpyrtry
  2306. dcr a ;count down retries
  2307. sta fpyrtry
  2308. jrnz fpy$rsek
  2309. fpy$erx:
  2310. mvi a,1 ;giving up...too many errors
  2311. jmpr hstexit
  2312. ;
  2313. ;come here when positioned to right track
  2314. noseek:
  2315. mvi a,maxrtr ;reset retry count
  2316. sta fpyrtry
  2317. fpy$rtr:
  2318. ; |10|
  2319. ;set up for floppy dma call
  2320. MVI A,io$fdata ;port # for DMA command block
  2321. MVI C,01 ;set up DMA channel mux select
  2322. ;
  2323. call loadmar ;set up z80-dma
  2324. fpynxrw:
  2325. lda fpycmd ;issue read or write command
  2326. call xqt ; and wait for completion
  2327. in io$fdst
  2328. ani fsdlost+fscrc+fsrnf+fsnrdy+fswprot ;check for errors
  2329. jrnz fpy$err ;jump if error
  2330. sub a ;else clear error flag
  2331. hstexit:
  2332. sta erflag ;save error flag
  2333. mvi a,montime ;set up motor timeout
  2334. sta timecntr
  2335. ret ;return to caller
  2336. ;
  2337. ;Here to home drive
  2338. restore:
  2339. mvi a,rate ;use normal rate
  2340. jmpr restx ;share code with error recovery
  2341. ;
  2342. ;Here to recover from seek error
  2343. resterr:
  2344. mvi a,rate+1 ;use slower rate
  2345. restx:
  2346. lbcd hstdsk ;index into track table
  2347. mvi b,0
  2348. lxi h,trktbl
  2349. dad b
  2350. mvi m,0 ;force track to 0
  2351. ;and fall into XQT to issue home command
  2352. ;
  2353. ;This routine issues fdc command and waits for IRQ
  2354. xqt:
  2355. out io$fdcmd ;send the command
  2356. xqtl:
  2357. in io$pioad ;look at irq line
  2358. bit 4,a
  2359. jrz xqtl ;loop till true
  2360. ret
  2361. ;
  2362. ;
  2363. ;Here to recover from read or write error
  2364. fpy$err:
  2365. lda fpyrtry ;check retry count
  2366. dcr a ;bump it
  2367. sta fpyrtry
  2368. jnz fpy$rtr ;retry if not exhausted
  2369. call resterr ;out of retries...home drive and quit
  2370. jmp fpy$erx
  2371. ;
  2372. ; TITLE XEBEC-GORMAN WINCHESTER DISK **
  2373. ; 03/23/82 5 MEG COMPRESSED VERSION JRT
  2374. ; 08/12/82 Multi-type disks configured from boot JRT
  2375. ; ===================================
  2376. ;
  2377. hdrw: ;this is the hard disk XEBEC driver
  2378. ; SELECT DRIVE
  2379. ; A= the drive to select, codes 6-7 indicate multi-volume drvs |10|
  2380. ; C= Command Read or Write
  2381. ;
  2382. ; we got here thru the logical to physical disk table and being
  2383. ; not equal to Mdrive the only alternatives are 4,6=drive 0 5,7=drive 1
  2384. mov b,a ; |10|
  2385. cpi maxfloppy+maxharddisk ; hard disk ? |15|
  2386. mvi a,1 ; a := possible error result |15|
  2387. rnc ; exit if not hard disk drive |15|
  2388. mov a,b ; a := disk number |15|
  2389. ani 1 ; resource as drive select lsb=drive |10|
  2390. jrz sdrv0
  2391. mvi a,drvsel1
  2392. sdrv0: sta dcb$drv ;set the drive to select
  2393. ;
  2394. mov a,c
  2395. sta dcb$cmd ;set the read or write command
  2396. ;
  2397. ;GET RANDOM ADDRESS.
  2398. ; We are playing games with tracks and sectors/track
  2399. ; to avoid possible interaction with deblocking vs the floppys.
  2400. ; Even though we have 32 256 byte sectors/surface and 4 surfaces
  2401. ; CPM sees it as 32 128 byte sectors and 2*4*152 tracks
  2402. ;
  2403. ; Xebec however sees only 1 type of address, a logical sector number
  2404. ; so we must glue the tracks and sectors back together, fortunately
  2405. ; sectors/track is a power of 2
  2406. ;
  2407. ; The higher capacity drives are viewed as having multiple 5 Meg
  2408. ; volumes, 6= second half of drive 0, 7=second half of drive 1
  2409. ;
  2410. lhld hsttrk ; hl := host track
  2411. rept 4
  2412. dad h ; hl := 16 * host track
  2413. endm
  2414. lda hstsec ;Deblock thinks there are 16 sects/track
  2415. add l ; a := (16 * host track) + host sector
  2416. mov l,a ; |10|---------
  2417. ; Test the size of the logical address
  2418. xchg
  2419. lxi h,-19199 ;the size of 5 Meg
  2420. dad d
  2421. jrc oversiz
  2422. ; Multi volume drive? The drive select is in B
  2423. xchg
  2424. lxi d,19200
  2425. bit 1,b
  2426. jrz notten
  2427. dad d
  2428. notten:
  2429. mov a,l ; |10|---------
  2430. sta dcb$ctrk+1 ;MSB IS FIRST
  2431. mov a,h
  2432. sta dcb$ctrk ;XEBEC IS BACKWARDS
  2433. ;
  2434. ;Load the DMA using code common with floppy
  2435. ;
  2436. MVI C,DMAHD ;set up Dma mux select
  2437. MVI A,HD$DATA ;Port address for Dma block
  2438. ;
  2439. CALL loadmar
  2440. ;
  2441. ; Number of sectors is always 1 and is a constant in the control block
  2442. ;
  2443. ; NOW COMMAND THE CONTROLLER
  2444. ;
  2445. CALL ACQUIRE
  2446. JRC HDK$DOWN
  2447. ;
  2448. LXI H,DCB$CMD
  2449. LXI B,600H+HD$DATA ;COUNT 6 BYTES TO DATA PORT
  2450. HXQLP: IN STCS
  2451. ANI GCMD+DTAREQ
  2452. JRNZ HXQLP
  2453. OUTI
  2454. JRNZ HXQLP
  2455. ;
  2456. ; CONTROLLER NOW EXECUTES ENABLE DMA AND COMPLETION INTRPT
  2457. ;
  2458. OUT ENDMA ;ANY VALUE
  2459. NOP ;DO NOT REMOVE
  2460. XWAT: IN STCS ;CHECK IF DONE
  2461. ANI CSTAT+DTAREQ
  2462. JRNZ XWAT ;THIS IS THE NON INTERRUPT VERSION
  2463. ;
  2464. ; DO DISABLES AND CHECK STATUS
  2465. OUT DISDMA
  2466. CALL WBUSY
  2467. ;
  2468. ; IF ERROR READ STATUS BYTES TO DCB FOR DEBUG
  2469. ;
  2470. JRNZ HDK$ER
  2471. ;
  2472. ; HANDLE REQUEST COMPLETION.
  2473. ;
  2474. HDK$EXIT:
  2475. STA erflag
  2476. RET ;COMPLETE REQUEST.
  2477. ;
  2478. oversiz:
  2479. HDK$DOWN:
  2480. MVI A,1
  2481. STA erflag
  2482. RET
  2483. ;
  2484. ; COMMON ERROR HANDLER
  2485. ;
  2486. HDK$ER: ;DO A REQUEST-SENSE TO GET INFO
  2487. CALL ACQUIRE
  2488. JRC HDK$DOWN
  2489. MVI A,RQSEN
  2490. CALL CKGCMD
  2491. LDA DCB$DRV
  2492. CALL CKGCMD
  2493. CALL GIVCMD
  2494. LXI B,400H+HD$DATA
  2495. LXI H,DCB$RSTA
  2496. RQDLP: IN STCS
  2497. CPI 0FH ;DATA FROM CONTROLLER
  2498. JRNZ RQDLP
  2499. INI
  2500. JRNZ RQDLP
  2501. ;
  2502. ; GET IN THE STATUS AND COMPLETION FOR RQSEN
  2503. ;
  2504. CALL WBUSY
  2505. LDA DCB$RSTA
  2506. SUI 98H ;ECC CORRECTED
  2507. JR HDK$EXIT ;NZ=UNRECOVERABLE ERROR.
  2508. ;
  2509. ACQUIRE:
  2510. IN STCS ;CHECK CONTROLLER ALREADY BUSY
  2511. ANI CBUSY
  2512. STC
  2513. RZ ;low is busy
  2514. MVI A,1 ;SELECT CONTROLLER 1
  2515. OUT SEL
  2516. MVI B,0FFH ;AN ARBITRARY TIMEOUT
  2517. RDYLP: IN STCS
  2518. ANI CBUSY
  2519. RZ ;RETURN OK
  2520. DJNZ RDYLP
  2521. STC
  2522. RET ;DID NOT GO BUSY--ERROR
  2523. ;
  2524. ; WAIT FOR DONE ON SHORT COMMAND--TEST DRV AND GET SENSE
  2525. ;
  2526. WBUSY: IN STCS ;Test the interface status
  2527. ANI CSTAT+DTAREQ
  2528. JRNZ WBUSY
  2529. IN HD$DATA ;Read in the completion status
  2530. MOV B,A
  2531. WDONE: IN STCS
  2532. ANI CDONE+DTAREQ
  2533. JRNZ WDONE
  2534. IN HD$DATA ;Read in the Done Byte and discard
  2535. MOV A,B
  2536. ANI ERHDK ;Set the status for test after return
  2537. RET
  2538. ;
  2539. ;
  2540. GIVCMD: MVI A,0
  2541. MVI B,4
  2542. GCLP: CALL CKGCMD
  2543. DJNZ GCLP
  2544. RET
  2545. ;
  2546. CKGCMD: PUSH PSW
  2547. CKGLP: IN STCS
  2548. ANI GCMD+DTAREQ
  2549. JRNZ CKGLP
  2550. POP PSW
  2551. OUT HD$DATA
  2552. RET
  2553. ;
  2554. ;Routine to initialize z80-dma
  2555. ; at entry C= DMA mux channel to select
  2556. ; DMARW=Dma direction DMARW+1 =Read or Write DMA command, |10|
  2557. ; A= >DCPORT= io$fdata or HD$DATA
  2558. ;
  2559. ; sets DCDIR= Direction A port or B port
  2560. loadmar:
  2561. STA DCPORT ;set the port address into the command tbl
  2562. lhld bufptr ; |10|
  2563. shld bptr ; bufptr is used by the copy utilities |10|
  2564. lxi h,DMARW ; |10|
  2565. mov a,m ; |10|
  2566. inx h
  2567. STA DCDIR ;in the command table
  2568. ;
  2569. in io$pioad
  2570. ani DMAMSK ;throw dma switch to correct controller
  2571. ora C
  2572. out io$pioad
  2573. lxi b,600h+io$dma ;send 6 resets to z80-dma
  2574. mvi a,0c3h
  2575. resdma:
  2576. outp a
  2577. djnz resdma
  2578. ;
  2579. mvi b,dmte-dmtb ;command+address+count+table |10|----------
  2580. outir ;send commands to z80-dma
  2581. ret
  2582. ;
  2583. ;
  2584. ;z80-dma read command table
  2585. DMARW: ds 1 ;Temp for DCDIR
  2586. ;
  2587. dmtb: ds 1 ;Command read or write
  2588. bptr: ds 2 ;put it here where we use it
  2589. bufcnt: dw 256 ;the count constant |10|----------
  2590. db 14h ;port a mem, increment addresses
  2591. db 28h ;port b i/o, fixed addresses
  2592. db 85h ;byte mode, next port lower
  2593. DCPORT: DS 1 ;io$fdata OR HD$DATA ;port address of fdc
  2594. db 9ah ;ready active high
  2595. db 0cfh ;load
  2596. DCDIR: DS 1 ;source is b, transfer only
  2597. ;01 FOR FPY->MEM, 05 FOR M->FPY
  2598. db 0cfh ;load
  2599. db 087h ;enable dma (start)
  2600. dmte:
  2601. ;
  2602. ;
  2603. ; Drive not ready error branches here
  2604. DRVNRDY:
  2605. LDA HSTDSK ; generate error message
  2606. ANI 3
  2607. ADI 'A' ; with correct drive name
  2608. STA DVNAME
  2609. LXI H,NRDYMSG ; and print it
  2610. CALL PRMSG
  2611. WAITRDY:
  2612. IN IO$FDST ; get floppy controller status byte
  2613. ANI FSNRDY ; check ready status
  2614. JRZ CRLF ; exit if it became ready
  2615. CALL XCONST ; check console
  2616. ORA A
  2617. JRZ WAITRDY ; loop if not ready
  2618. CALL XCONIN ; get response
  2619. CALL CRLF
  2620. PERMERR:
  2621. LDA IPLDSK ; Get user 0/IPL drive
  2622. STA CDISK ; force IPL drive selected
  2623. JMP WBOOT ; branch out of error
  2624. CRLF:
  2625. LXI H,CRLFMSG
  2626. JMP PRMSG ; do CR & LF
  2627. ; RET ; and go continue disk I/O
  2628. ;
  2629. CRLFMSG:
  2630. DB 13,10,0
  2631. NRDYMSG:
  2632. DB 7,13,10,'Drive '
  2633. DVNAME DB 0
  2634. DB ' not ready',0
  2635. ;
  2636. ;
  2637. ;
  2638. ;Turn on the floppy motors and test if they were already on
  2639. motoron:
  2640. lda fpy$ctrl ;look at current control bits
  2641. ani 0b0h ;eliminate precomp and selects
  2642. ora e ;get passed precomp and select
  2643. ori fdenab ;make sure enable remains
  2644. bit 5,a ;test motor on bit
  2645. setb 5,a ;and force it on
  2646. newctrl:
  2647. sta fpy$ctrl ;save control byte
  2648. out io$fdctl ;and send it
  2649. ret
  2650. ;
  2651. ;Decrement motor delay count if pending...turn off if time
  2652. ;
  2653. chkmotor:
  2654. lda timecntr ; first see if delay pending
  2655. ora a
  2656. rz ; nope
  2657. if (not interrupts)
  2658. lhld timecntp ; do prescale count
  2659. dcx h ; if interrupts not available
  2660. shld timecntp
  2661. mov a,h
  2662. ora l
  2663. rnz ; quit unless prescale exhausted
  2664. lda timecntr
  2665. endif
  2666. dcr a ;count down time
  2667. sta timecntr
  2668. jrz motoroff ;kill motors if time
  2669. cpi montime/2 ;time to kill select light?
  2670. rnz
  2671. lda fpy$ctrl ;get current control byte
  2672. ani 0f0h ;remove select bits
  2673. jmpr newctrl ;send new control byte
  2674. motoroff:
  2675. lda fpy$ctrl ;get control byte
  2676. res 5,a ;reset motor on bit
  2677. jmpr newctrl ;go send it
  2678. ;
  2679. ;
  2680. if memorydisk
  2681. memoryread:
  2682. call checkwritehst ; write out host buffer if necessary
  2683. call memorybase ; hl := memory base, a := a-segment map offset
  2684. lded bufptr ; de := host buffer index (destination)
  2685. push d ; save for later
  2686. call memorymove ; move into host buffer, reset write flag
  2687. pop h ; hl := host buffer index (source)
  2688. lded dmaadr ; de := dma buffer (destination)
  2689. lxi b,128 ; bc := buffer size
  2690. ldir ; copy into dma buffer
  2691. jmpr memorydone ; done transfer |12|
  2692. memorywrite:
  2693. call checkwritehst ; write out host buffer if necessary
  2694. lhld bufptr ; hl := host buffer index
  2695. push h ; save for later
  2696. xchg ; de := host buffer index (destination)
  2697. lhld dmaadr ; hl := dma buffer (source)
  2698. lxi b,128 ; bc := buffer size
  2699. ldir ; copy into host buffer
  2700. call memorybase ; hl := memory base, a := a-segment map offset
  2701. xchg ; de := memory base (destination)
  2702. pop h ; hl := host buffer index (source)
  2703. memorymove:
  2704. lxi b,128 ; bc := block size (size)
  2705. di ; turn off interrupts
  2706. out io$pmapa ; select memory disk into a-segment
  2707. ldir ; copy memory
  2708. lda pmapa$current ; a := current setting of io$pmapa
  2709. out io$pmapa ; select default a-segment
  2710. ei ; enable interrupts
  2711. memorydone: ; succesful transfer |12|
  2712. mvi a,mdrive ; a := mdrive |12|
  2713. sta hstdsk ; mark mdrive use of host buffer |12|
  2714. sub a ; a := 0 |12|
  2715. sta hstwrt ; reset host write flag |12|
  2716. sta hstact ; reset host active flag
  2717. sta unacnt ; reset unallocated count |2.27.02|
  2718. ret ; all done (return with not errors, a = 0)
  2719. memorybase:
  2720. ; return hl = memory index, a = map offset
  2721. ; memory index := 4000h + (sector * 128) + (track * 8K)
  2722. ; map offset := mdisk$base + (track * 8)
  2723. ;
  2724. lda lac$sec ; a := sector number (0 - 63)
  2725. rrc ; a := rotate right (sector)
  2726. mov h,a ; save in h
  2727. ani 80h ; a := (sector mod 2) * 128
  2728. mov l,a ; l := (sector mod 2) * 128
  2729. mov a,h ; h := rotate right (sector)
  2730. ani 1fh ; a := sector / 128
  2731. adi 40h ; add in a-segment base (4000 hex)
  2732. mov h,a ; hl := memory index
  2733. lda sektrk ; a := track
  2734. ani 1fh ; make sure there are only 32 segments
  2735. add a ; a := track * 2
  2736. add a ; a := track * 4
  2737. add a ; a := track * 8
  2738. add a ; a := track * 16
  2739. aci mdisk$base ; a := a-segment map offset |2.27.01|
  2740. rnc ; exit if no carry generated |2.27.01|
  2741. inr a ; add in carry |2.27.01|
  2742. ret
  2743. endif
  2744. ;
  2745. ;
  2746. ;
  2747. ;
  2748. ;*****************************************************
  2749. ;* *
  2750. ;* Unitialized RAM data areas *
  2751. ;* *
  2752. ;*****************************************************
  2753. ;
  2754. ;
  2755. ; Macro to generate a pre-loaded function key
  2756. key macro str
  2757. @a set $+8
  2758. db str
  2759. db 0
  2760. if $ lt @a
  2761. ds @a-$
  2762. endif
  2763. endm
  2764. ;
  2765. ;
  2766. ; Screen driver variables
  2767. ;
  2768. L80$40: ds 1 ; 40-column flag
  2769. VPOS: ds 1 ; Vertical position (line)
  2770. HPOS: ds 1 ; Horizontal position (column)
  2771. ATTRIB: ds 1 ; current character attributes
  2772. ESCFLG: ds 1 ; Nonzero if in escape sequence
  2773. LTABPTR:ds 2 ; Pointer to start of line address table
  2774. LINLEN: ds 1 ; Number of characters per line
  2775. ukip: ds 2 ; Pointer to key string being read
  2776. ukop: ds 2 ; Pointer to key string being loaded
  2777. uktbl: ds 256 ; Storage for user func key strings (F1-F32)
  2778. ; Pre-initialized function keys (white)
  2779. key 'V'-40h ; insert lock
  2780. key 'G'-40h ; del char
  2781. key 'RUN'
  2782. key 'P'-40h ; print screen
  2783. key 0D4h ; calc mode
  2784. key '^'-40h ; home
  2785. key 'K'-40h ; up-arrow
  2786. key 'J'-40h ; down-arrow
  2787. key 'L'-40h ; right-arrow
  2788. key 'H'-40h ; left-arrow
  2789. key 'Y'-40h ; del line
  2790. key 'LOAD'
  2791. key 'CONT'
  2792. key 0D3h ; shifted calc mode
  2793. key 'Z'-40h ; clear
  2794. key 'E'-40h ; cntl up arrow
  2795. key 'X'-40h ; cntl down arrow
  2796. key 'D'-40h ; cntl right arrow
  2797. key 'S'-40h ; cntl left arrow
  2798. key 'S'-40h ; stop
  2799. key 7fh ; cntl backspace
  2800. key 'F'-40h ; cntl tab
  2801. ;
  2802. SPSAVE: ds 2 ; Place to save caller's stk ptr
  2803. ds 32
  2804. LOCLSTK EQU $ ; Local stack area
  2805. ;
  2806. ;
  2807. ; Blocking/deblocking driver variables
  2808. ;
  2809. sekdsk: ds 1 ;seek disk number
  2810. sektrk: ds 2 ;seek track number
  2811. seksec: ds 1 ;seek sector number
  2812. lacsec ds 1 ;interlaced sector number
  2813. ;
  2814. hstdsk: ds 1 ;host disk number
  2815. hsttrk: ds 2 ;host track number
  2816. hstsec: ds 1 ;host sector number
  2817. ;
  2818. sekhst: ds 1 ;seek shr secshf
  2819. hstact: ds 1 ;host active flag
  2820. hstwrt: ds 1 ;host written flag
  2821. ;
  2822. unacnt: ds 1 ;unalloc rec cnt
  2823. unadsk: ds 1 ;last unalloc disk
  2824. unatrk: ds 2 ;last unalloc track
  2825. unasec: ds 1 ;last unalloc sector
  2826. ;
  2827. erflag: ds 1 ;error reporting
  2828. rsflag: ds 1 ;read sector flag
  2829. readop: ds 1 ;1 if read operation
  2830. wrtype: ds 1 ;write operation type
  2831. dmaadr: ds 2 ;last dma address
  2832. hstbuf: ds hstsiz ;host buffer
  2833. ;
  2834. records$per$block:
  2835. ds 1 ; CP/M (128 byte) records/block
  2836. ;
  2837. ;
  2838. ENDEF ; generate bdos data areas
  2839. if coninterrupt
  2840. conbuffer: ds conbuffersize ; console interrupt buffer
  2841. endif
  2842. end$bios: ; last label in data area
  2843. ;
  2844. ;
  2845. ;***********************************************************************
  2846. ;* *
  2847. ;* Initialization section - the following code is used only *
  2848. ;* during startup. It overlays the uninitialized data areas *
  2849. ;* to save space. *
  2850. ;* *
  2851. ;***********************************************************************
  2852. ;
  2853. ;
  2854. rorg uktbl
  2855. ;
  2856. ; Routine to initialize the internal screen for use by CP/M
  2857. CRT$INIT:
  2858. PUSHIX
  2859. MVI A,80H ; Enable text
  2860. OUT IO$HCOL
  2861. MVI A,15 ; Check for presence of 6845
  2862. OUT IO$CRTA ; to decide if we have 80 col. screen
  2863. SUB A
  2864. STA ESCFLG ; Not in escape sequence
  2865. STA ATTRIB ; No attributes set
  2866. STA L80$40 ; Assume 80 col.
  2867. OUT IO$CRTD
  2868. LXI H,LTAB80
  2869. SHLD LTABPTR
  2870. MVI A,80
  2871. STA LINLEN
  2872. IN IO$CRTD+2 ; Now see if there's a device on that port
  2873. ORA A ; 0 means yes, 0FFH (open circuit) means no
  2874. JRZ GOT80
  2875. ; Reset params for 40 col screen
  2876. if displayclock
  2877. lxi h,second$interrupt
  2878. mvi m,0c9h ; put RET instruction in second$interrupt
  2879. endif
  2880. MVI A,0FFH
  2881. STA L80$40
  2882. LXI H,LTAB40
  2883. SHLD LTABPTR
  2884. MVI A,40
  2885. STA LINLEN
  2886. GOT80: MVI A,5 ; Get VRAM
  2887. OUT IO$SYS
  2888. CALL EHOME ; Clear and home the screen
  2889. MVI A,1 ; Kill VRAM
  2890. OUT IO$SYS
  2891. MVI A,10
  2892. OUT IO$CRTA ; Put up underscore cursor
  2893. OUT IO$CRTD
  2894. MVI A,11
  2895. OUT IO$CRTA
  2896. OUT IO$CRTD
  2897. CALL SETCUR ; Position cursor home
  2898. MVI A,5
  2899. OUT IO$DRTBC ; Enable keyboard
  2900. MVI A,0E8H
  2901. OUT IO$DRTBC
  2902. POPIX
  2903. RET
  2904. ;
  2905. if reloc
  2906. psize equ 0
  2907. else
  2908. psize equ msize
  2909. endif
  2910. ;
  2911. sgnmsg: db psize/10+'0',psize-psize/10*10+'0'
  2912. db 'k CP/M vers '
  2913. db version+'0'
  2914. db '.'
  2915. db (revision/10)+'0'
  2916. db (revision mod 10)+'0'
  2917. db ' for Monroe '
  2918. sgnms1: db 'OC 8800'
  2919. if production ne true
  2920. db ' Experimental '
  2921. db (production/10)+'0'
  2922. db (production mod 10)+'0'
  2923. endif
  2924. db ' '
  2925. db (month/10)+'0'
  2926. db (month mod 10)+'0'
  2927. db '/'
  2928. db (day/10)+'0'
  2929. db (day mod 10)+'0'
  2930. db '/'
  2931. db (year/10)+'0'
  2932. db (year mod 10)+'0'
  2933. db 0 ; end of text
  2934. ;
  2935. lstitb: db 0,30h,1,0,2,0e8h,3,0e1h,4 ; initialize list
  2936. lstibaud: db 044h,5,0eah,0 ; reg 4 is baud rate
  2937. lstitbsize equ $-lstitb
  2938. ;
  2939. ptritb: db 0,30h,1,0,2,0d8h,3,0c1h,4 ; initialize printer
  2940. ptribaud: db 0c4h,5,0eah,0 ; reg 4 is baud rate
  2941. ptritbsize equ $-ptritb
  2942. ;
  2943. uc1itb: db 0,30h,1,0,2,0d0h,3,0c1h,4 ; initialize user port
  2944. uc1ibaud: db 044h,5,0eah,0 ; reg 4 is baud rate
  2945. uc1itbsize equ $-uc1itb
  2946. ;
  2947. keyitb: db 0,30h,2,0e0h ; set interrupt vector
  2948. if coninterrupt
  2949. db 1,14h ; enable receiver interrupt w/status
  2950. endif
  2951. db 0
  2952. keyitbsize equ $-keyitb
  2953. ;
  2954. ;*****************************************************************
  2955. ;
  2956. rorg loclstk
  2957. ;
  2958. ; Print sign-on, and initialize all I/O devices and parameters.
  2959. ; Register C contains the IPL drive number in the lower nibble.
  2960. ; It also contains a flag in the ms bit: 0 = 128K machine
  2961. ; 1 = 256K machine
  2962. ;
  2963. boot: lxi sp,0200H ; put stack in a safe place
  2964. mov a,c ; a := machine flag/boot drive
  2965. ani 80h ; 256k machine ?
  2966. jnz is256k ; skip if 256k machine
  2967. mvi a,55 ; a := sectors on mdisk for 128k machine
  2968. sta mdisk$dsm ; update number of blocks in m-disk
  2969. is256k: pushix ; save machine flag/boot drive
  2970. pop b ; c := machine flag/boot drive
  2971. mov a,c ; remember which drive was booted
  2972. ani 7 ; |10|
  2973. sta ipldsk
  2974. sta cdisk ; select booted disk
  2975. sub a ; a := 0
  2976. sta timecntr ; reset floppy motor timer
  2977. mov a,b
  2978. sta fpyctrl ;current drive control byte
  2979. call crt$init ;initialize crt driver
  2980. lda l80$40 ;look at 80/40 column flag
  2981. ani 1 ;and leave in iobyte so applications
  2982. sta iobyte ; know screen width
  2983. jrz boot1
  2984. mvi a,'E' ;make signon reflect model number
  2985. sta sgnms1
  2986. boot1:
  2987. if interrupts
  2988. di
  2989. im2 : Vector table interrupt mode
  2990. mvi a,vectortbl/256 ; load interrupt base register
  2991. stai ; Interrupt page register := A
  2992. mvi a,0f0h ; set CTC interrupt vector again
  2993. out io$ctc0
  2994. mvi a,start$ctc3
  2995. out io$ctc3
  2996. mvi a,oneslice ; setup for 20 msec interrupt
  2997. out io$ctc3
  2998. ; ei-- don't enable here get other things done first |10|
  2999. endif
  3000. lxi h,rbaud
  3001. mvi a,45h
  3002. out io$ctc0 ;set modem port baud rate
  3003. mov a,m
  3004. out io$ctc0
  3005. inx h
  3006. mov a,m ;set sio divider also
  3007. sta ptribaud ; |11|
  3008. inx h
  3009. mvi a,45h
  3010. out io$ctc1 ;set AUX port baud rate
  3011. mov a,m
  3012. out io$ctc1
  3013. inx h
  3014. mov a,m
  3015. sta uc1ibaud ;set sio divider too |11|
  3016. inx h
  3017. mvi a,45h
  3018. out io$ctc2 ;set printer baud rate
  3019. mov a,m
  3020. out io$ctc2
  3021. inx h
  3022. mov a,m
  3023. sta lstibaud ;set sio divider too |11|
  3024. lxi b,(lstitbsize*256)+io$drtac ; |11|
  3025. lxi h,lstitb ;init printer DART
  3026. outir
  3027. lxi b,(ptritbsize*256)+io$sioac ; |11|
  3028. lxi h,ptritb ;init rdr/pun SIO
  3029. outir
  3030. lxi b,(uc1itbsize*256)+io$siobc ; |11|
  3031. lxi h,uc1itb ;init alt. cons. SIO
  3032. outir
  3033. if interrupts
  3034. lxi b,(keyitbsize*256)+io$drtbc
  3035. lxi h,keyitb ;init keyboard interrupt vector
  3036. outir
  3037. endif
  3038. lxi h,sgnmsg ;say hello to the nice folks
  3039. call prmsg
  3040. lxi h,0
  3041. shld ukip ;deactivate function keys
  3042. shld ukop
  3043. lxi d,7 ;init them to contain their own values
  3044. lxi h,uktbl ;(7 chars + null per key)
  3045. lxi b,32*256+80H ;32 keys, values 80h thru 9Fh
  3046. zuklup: mov m,c ; store key value
  3047. inx h
  3048. mvi m,0 ; follow with null
  3049. dad d ; point to next key
  3050. inr c ; generate next key value
  3051. djnz zuklup ; repeat 32 times
  3052. if memorydisk
  3053. ; |2.27.01| -----------------------
  3054. di ; initialize with interrupts off
  3055. call initialize$mdisk ; initialize mdisk
  3056. jmp mdisk$initialized ; finish rest of system initialization
  3057. initialize$mdisk:
  3058. lxi h,ccp ; hl := ccp base
  3059. lxi d,4000h+100h ; de := sector 1 of track 0 (base 0)
  3060. lxi b,bios-ccp ; bc := size of block to copy
  3061. mov a,m ; a := byte to put into first position
  3062. call move$to$memory$disk ; copy ccp and bdos to mdisk
  3063. lxi h,6000h ; hl := base of directory (track 1)
  3064. lxi d,6000h+1 ; de := second byte in directory
  3065. lxi b,(clearmemorydisk*128)-1 ; bc := segment size to clear
  3066. mvi a,0e5h ; a := byte to clear memory with
  3067. move$to$memory$disk:
  3068. sta first$mdisk$byte ; save first byte
  3069. mvi a,mdisk$base ; swap in first memory disk segment
  3070. out io$pmapa
  3071. lda first$mdisk$byte ; a := first byte
  3072. mov m,a ; set first byte
  3073. ldir ; move remaining bytes
  3074. lda pmapa$current ; a := current setting of io$pmapa
  3075. out io$pmapa ; select default a-segment
  3076. ret
  3077. first$mdisk$byte: db 0 ; first byte to set in mdisk
  3078. mdisk$initialized: ; all done with mdisk
  3079. ; -------------------- |2.27.01|
  3080. endif
  3081. ;
  3082. ;--|10|--
  3083. ; Set Cpm disk availability based on boot prom values
  3084. ;
  3085. Ms8type equ 1
  3086. Cpmtype equ 2
  3087. Untype equ 3 ;formatted but not allocated
  3088. Ofltype equ 4 ;test drive says drive down at boot time
  3089. hdtype0 equ 13h ;address of data passed from prom
  3090. hdtype1 equ 23h
  3091. ; for MP/M compat. these are not used after Coldst.
  3092. ;
  3093. ; First check nonexistant or allocated to MS-8
  3094. ; if value is 55 then old boot prom, use the defaults
  3095. ;
  3096. lxi h,hdtype0
  3097. lxi d,hd$drvs
  3098. mov a,m ;the Os type byte
  3099. inx h
  3100. mov c,m ;control byte--same for both drives
  3101. inx h
  3102. cpi 55h
  3103. jrz dskset ;the loaded image has constants in place
  3104. ;
  3105. mvi b,4 ;the first drive is always 4
  3106. call sethd ;sets the logical$disk for online and size
  3107. lxi h,hdtype1
  3108. mov a,m
  3109. inx h
  3110. inx h ;skip cntl byte--this is a XEBEC
  3111. mvi b,5 ;the second drive is always 5
  3112. call sethd ;last call has incremented DE
  3113. ;
  3114. ; Load the Drive type control bits to the DCB
  3115. mov a,c
  3116. sta DCB$CTL
  3117. ; -------------------|10|
  3118. dskset: lxi h,wboot ;prevent this code from being accessed again
  3119. shld bios+1 ;by changing cold boot vector to warm
  3120. lxi h,ccp ;select CCP cold entry point
  3121. jmp gocpm ;initialize and go to cp/m
  3122. ; |10|-------------------
  3123. ; Set the Logical$disk table according to the sizes
  3124. ; A 5 Meg drive system 0=E: 1=F:
  3125. ; A 10 Meg drive system 0=E:+F: 1=G:+H:
  3126. ; Future: A 15 Meg drive system 0=E:+F:+G: 1=H:+I:+J:
  3127. sethd: cpi Cpmtype
  3128. jrz settype
  3129. cpi Untype
  3130. jrz settype
  3131. mvi b,0ffh ;mark it non-existant
  3132. settype:
  3133. mov a,b ;offline or drive #
  3134. stax d ;mark this drive
  3135. inx d
  3136. inx h ;skip the size MSB
  3137. mov a,m ;the middle byte of size
  3138. cpi 04ah ;19200
  3139. rz ;can only set one partition on 5 meg
  3140. ;
  3141. mov a,b
  3142. ori 2 ;4+2=6,5+2=7 ff+2=ff
  3143. stax d ;set the second partition of drive
  3144. inx d
  3145. ret
  3146. ; -----------|10|
  3147. ;
  3148. code$size equ $-ccp
  3149. ;
  3150. if $ lt end$bios
  3151. ds end$bios-$ ; force MAC to show true size of BIOS
  3152. endif
  3153. ;
  3154. end
  3155.