source: buchla-68k/rom/bios.s@ 4b63bf3

Last change on this file since 4b63bf3 was 3370595, checked in by Thomas Lopatic <thomas@…>, 7 years ago

Fix symbol collisions.

  • Property mode set to 100644
File size: 104.3 KB
Line 
1|*******************************************************************************
2| *
3| bios.s -- BIOS for the Buchla 700 and NASA 3D Helmet Display *
4| ------ -------------------------------------------------- *
5| *
6| See VM1,VM2 and VDATE for version and date *
7| Written by D.N. Lynx Crowe *
8| *
9| Very loosely based on ideas from: *
10| *
11| "Atari ST Internals", by Abacus Software, *
12| "A Hitchhiker's Guide to the BIOS", by Atari, *
13| "DOS Technical Reference", by IBM, *
14| "DOS/360", by IBM,
15| "CP/M" , by Digital Research, and, of course, *
16| "Unix (tm)", by AT&T, et al. *
17| *
18| After all, Why re-invent the wheel? *
19| *
20| Some of the functions are the same as Ataris, but quite a few are different, *
21| and our I/O configuration is much different, so BEWARE! Make no *
22| assumptions, and read the documentation and comments very carefully. *
23| *
24| Especially watch out for the extended BIOS functions. Most of them *
25| are nothing at all like the Atari / GEMDOS extended bios functions, *
26| and even the ones that are similar have different numbers. *
27|*******************************************************************************
28
29 .text
30
31| Version and date
32| ----------------
33VM1 = 18 | First part of version number
34VM2 = 0 | Second part of version number
35VDATE = 0x19880620 | Version date
36
37BUCHLA = 1 | Non-Zero for Buchla 700, 0 for NASA
38NASASIO = 0 | Non-zero for NASA, 0 for Buchla addr.
39
40FL_SKR = 0x00 | Seek rate (WD1772, 6Ms/step)
41|************************************************************************
42
43 .page
44
45 .xref start_ | Where ROMP starts
46 .xref errno | Start of ROMP bss space
47
48 .xdef basepage | Pseudo base page for romp
49 .xdef rsflag | Register save area overflow flag
50
51 .ifne BUCHLA
52
53 .xdef hdvini | Disk init
54
55 .endc
56
57 .xdef wzcrsh | ROMP crash flag
58 .xdef crshvc | Crash vector
59 .xdef crshsr | Crash SR
60 .xdef crshpc | Crash PC
61 .xdef crshsp | Crash SP
62 .xdef crshus | Crash USP
63 .xdef crshrg | Crash SP registers
64 .xdef crshst | Crash top of stack
65
66 .page
67
68 .ifne BUCHLA
69
70 .xdef hz_1k
71 .xdef hz_200
72 .xdef frclock
73 .xdef t1count
74 .xdef t2count
75 .xdef t3count
76
77 .xdef nflops
78 .xdef disknum
79 .xdef booted
80 .xdef seekrate
81 .xdef flock
82 .xdef fverify
83
84 .xdef retrycnt
85 .xdef wpstatus
86 .xdef wplatch
87 .xdef bootdev
88
89 .xdef cdev
90 .xdef ctrack
91 .xdef csect
92 .xdef cside
93 .xdef ccount
94
95 .xdef cdma
96 .xdef edma
97 .xdef tmpdma
98 .xdef rseed
99
100 .xdef savptr
101
102 .xdef flpsrsv
103 .xdef flpregs
104
105 .xdef dsb0
106 .xdef dsb1
107
108 .xdef dskmode
109 .xdef dskerrs
110 .xdef drvbpbs
111
112 .endc
113
114 .xdef biostop
115
116 .page
117
118| Some critical equates:
119| ----------------------
120| Interrupt masks
121| ---------------
122IPL3 = 0x0300 | IPL 3 value for sr
123IPL4 = 0x0400 | IPL 4 value for sr
124IPL7 = 0x0700 | IPL 7 value for sr (4 for debug)
125
126 .ifne BUCHLA
127
128INITIPL = IPL3+0x2000 | Initial Internal Priority Level
129
130 .endc
131
132 .ifeq BUCHLA
133
134INITIPL = IPL4+0x2000 | Initial Internal Priority Level
135
136 .endc
137
138| Memory allocation
139| -----------------
140 .ifeq BUCHLA
141
142TPA = 0x008000 | Put TPA 32K up from the bottom
143
144 .endc
145
146 .ifne BUCHLA
147
148TPA = 0x010000 | Put TPA 64K up from the bottom
149
150 .endc
151
152SSTACK = TPA | Put system stack just below TPA
153
154p_bbase = 0x0018 | Basepage offset to bss base
155p_blen = 0x001C | Basepage offset to bss length
156
157| It's magic ...
158| --------------
159FMAGIC = 0x87654321 | Magic for formatting
160RETRYIT = 0x10000 | Magic for re-try from criter
161RSMAGIC = 0x78563412 | Magic for register save area OK
162
163| Miscellaneous constants
164| -----------------------
165FCMAX = 0x00FFFFFF | Maximum frame counter value (24 bits)
166
167 .page
168
169| CFR0 Baud Rates:
170| ----------------
171BR_300 = 0x04
172BR_600 = 0x05
173BR_1200 = 0x06
174BR_1800 = 0x07
175BR_2400 = 0x08
176BR_3600 = 0x09
177BR_4800 = 0x0A
178BR_7200 = 0x0B
179BR_9600 = 0x0C
180BR_19K2 = 0x0D
181BR_EXT = 0x0F
182
183| CFR0 Stop bits (includes TBR select bit):
184| -----------------------------------------
185NSB_1 = 0x40
186NSB_2 = 0x60
187
188| CFR1 Number of Data Bits (includes MSB):
189| ----------------------------------------
190NDB_5 = 0x80
191NDB_6 = 0xA0
192NDB_7 = 0xC0
193NDB_8 = 0xE0
194
195| CFR1 Parity Selection:
196| ----------------------
197P_ODD = 0x04
198P_EVEN = 0x0C
199P_MARK = 0x14
200P_SPACE = 0x1C
201
202P_NONE = 0x00
203
204| Line Discipline:
205| ----------------
206L_NUL = 0x00 | No protocol
207L_XON = 0x01 | XON/XOFF
208L_RTS = 0x02 | RTS/CTS
209
210 .page
211
212| I/O Buffer Sizes:
213| -----------------
214SR1IBS = 256
215SR1OBS = 256
216SR2IBS = 256
217SR2OBS = 256
218
219 .ifne BUCHLA
220
221MC1IBS = 512
222MC1OBS = 256
223MC2IBS = 512
224MC2OBS = 256
225
226 .endc
227
228| Line Disciplines:
229| -----------------
230SR1DISC = L_XON
231SR2DISC = L_XON
232
233 .ifne BUCHLA
234
235MC1DISC = L_NUL
236MC2DISC = L_NUL
237
238 .endc
239
240| CFR Setings:
241| ------------
242SR1CFR0 = BR_9600+NSB_1
243SR1CFR1 = NDB_8+P_NONE
244SR2CFR0 = BR_9600+NSB_1
245SR2CFR1 = NDB_8+P_NONE
246
247 .ifne BUCHLA
248
249MC1CFR0 = BR_EXT+NSB_1
250MC1CFR1 = NDB_8+P_NONE
251MC2CFR0 = BR_EXT+NSB_1
252MC2CFR1 = NDB_8+P_NONE
253
254 .endc
255
256 .page
257
258| I/O Addresses:
259| --------------
260VSDDINIT = 0x200400 | VSDD initial register base address
261VSDDDATA = 0x200000 | VSDD data segment base address
262
263 .ifeq BUCHLA
264
265 .ifeq NASASIO
266
267SR1ACIA = 0x3A8001 | Serial-1 ACIA base address (BUCHLA)
268SR2ACIA = 0x3A8009 | Serial-2 ACIA base address
269
270 .endc
271
272 .ifne NASASIO
273
274SR1ACIA = 0x398001 | Serial-1 ACIA base address (NASA)
275SR2ACIA = 0x398009 | Serial-2 ACIA base address
276
277 .endc
278
279 .endc
280
281 .ifne BUCHLA
282
283FPUBASE = 0x180000 | FPU base address
284TIMER = 0x3A0001 | Timer base address
285LCD = 0x3A4001 | LCD driver base address
286SR1ACIA = 0x3A8001 | Serial-1 ACIA base address (BUCHLA)
287SR2ACIA = 0x3A8009 | Serial-2 ACIA base address
288MC1ACIA = 0x3AC001 | MIDI-1 ACIA base address
289MC2ACIA = 0x3AC009 | MIDI-2 ACIA base address
290FLOPPY = 0x3B0001 | Floppy controller base address
291PSG = 0x3B4001 | Sound chip base address
292LEDS = 0x3B8001 | LED driver base address
293ANALOG = 0x3BC001 | Analog processor base address
294
295| FPU address offsets and misc. values
296
297FPU_CTL = 0x4000 | FPU control
298
299FPU_IN = 0x4000 | FPU input address
300FPU_CLR = 0x6000 | FPU interrupt reset address
301
302FPU_RST = 0x0015 | FPU reset value
303
304| PSG address offsets
305
306PSG_RD = PSG | Read PSG data
307PSG_WL = PSG | Write PSG address latch
308PSG_WD = PSG+2 | Write PSG data
309
310 .endc
311
312| VSDD data structure offsets
313
314VSDD_REG = VSDDDATA | Registers
315VSDD_AT = VSDDDATA+0x0100 | Access Table
316
317 .ifne BUCHLA
318
319| Timer registers
320
321TIME_CRX = TIMER | Control register 1 or 3
322TIME_CR2 = TIMER+2 | Control register 2
323TIME_T1H = TIMER+4 | Timer 1 high byte
324TIME_T1L = TIMER+6 | Timer 1 low byte
325TIME_T2H = TIMER+8 | Tiemr 2 high byte
326TIME_T2L = TIMER+10 | Timer 2 low byte
327TIME_T3H = TIMER+12 | Timer 3 high byte
328TIME_T3L = TIMER+14 | Timer 3 low byte
329
330 .endc
331
332| ACIA Register offsets:
333| ----------------------
334ACIA_IER = 0 | ACIA IER offset
335ACIA_ISR = 0 | ACIA ISR offset
336ACIA_CSR = 2 | ACIA CSR offset
337ACIA_CFR = 2 | ACIA CFR offset
338ACIA_TBR = 4 | ACIA TBR offset
339ACIA_TDR = 6 | ACIA TDR offset
340ACIA_RDR = 6 | ACIA RDR offset
341
342 .page
343
344 .ifne BUCHLA
345
346| Floppy register offsets:
347| ------------------------
348DSKCMD = 0 | Command / status
349DSKTRK = 2 | Track
350DSKSEC = 4 | Sector
351DSKDAT = 6 | Data
352
353| Miscellaneous equates:
354| ----------------------
355FL_NC = 0x02 | Non-compensated R/W/F bit
356
357APISIZE = 256 | Analog processor buffer size
358
359| Floppy commands:
360| ----------------
361FL_RS = 0x80 | Read sector
362FL_RM = 0x90 | Read multiple
363FL_WS = 0xA0 | Write sector
364FL_WT = 0xF0 | Write track (format)
365FL_FR = 0xD0 | Force reset
366FL_SK = 0x10 | Seek
367FL_SV = 0x14 | Seek w/verify
368
369 .endc
370
371 .page
372
373| iorec structure definitions:
374| ----------------------------
375IORECLN = 40 | Length of an iorec structure
376
377ibuf = 0 | Input buffer base address
378ibufsize = 4 | Input buffer size (bytes)
379ibufhd = 6 | Input buffer head index
380ibuftl = 8 | Input buffer tail index
381ibuflow = 10 | Input buffer low water mark
382ibufhi = 12 | Input buffer high water mark
383obuf = 14 | Output buffer base address
384obufsize = 18 | Output buffer size (bytes)
385obufhd = 20 | Output buffer head index
386obuftl = 22 | Output buffer tail index
387obuflow = 24 | Output buffer low water mark
388obufhi = 26 | Output buffer high water mark
389cfr0 = 28 | ACIA CFR, MS bit = 0
390cfr1 = 29 | ACIA CFR, MS bit = 1
391flagxon = 30 | XON flag (non-zero = XOFF sent)
392flagxoff = 31 | XOFF flag (non-zero = active)
393linedisc = 32 | Line discipline flags
394erbyte = 33 | Last error byte
395isr = 34 | ACIA ISR on interrupt
396csr = 35 | ACIA CSR on interrupt
397errct = 36 | Error count (FRM/OVR/BRK)
398ibfct = 38 | Input buffer full count
399
400 .page
401
402| Error codes:
403| ------------
404ERR01 = -1 | All purpose error
405ERR02 = -2 | Drive not ready
406ERR03 = -3 | Unknown command
407ERR04 = -4 | CRC Error
408ERR05 = -5 | Invalid request
409ERR06 = -6 | Seek error
410ERR07 = -7 | Unknown media
411ERR08 = -8 | Sector not found
412ERR09 = -9 | End of media (out of paper)
413ERR10 = -10 | Write fault
414ERR11 = -11 | Read fault
415ERR12 = -12 | General mishap
416ERR13 = -13 | Write protected
417ERR14 = -14 | Media changed
418ERR15 = -15 | Unknown device
419ERR16 = -16 | Bad sectors
420ERR17 = -17 | Insert disk
421
422 .page
423
424| In the Beginning...
425| -------------------
426
427| Low PROM -- Contains the initial sp (unused), and the initial pc,
428| as well as some version and creation date stuff and a copyright message,
429| just to be thorough about it.
430
431begin: bra.s biosinit | Jump to bios init
432
433vermsg: .dc.b VM1,VM2 | Version number
434
435 .dc.l biosinit | Reset address (bios init)
436
437created: .dc.l VDATE | Creation date
438
439copyrite: .ascii "{Copyright 1988 by " | Copyright message
440 .asciz "D.N. Lynx Crowe}"
441
442 .dc.l 0 | Some padding
443
444 .page
445 .even
446
447| biosinit -- Setup the defaults for the BIOS
448| -------- -------------------------------
449biosinit: move.w #0x2700,sr | Set sup mode, no interrupts
450 move.l #SSTACK,a7 | Setup supervisor stack pointer
451
452 lea badtrap,a1 | Set default trap vector
453 adda.l #0x02000000,a1 | ... with trap # in 31..24
454 lea 8,a0 | ... for traps 2..255
455 move.l #253,d1
456
457binit1: move.l a1,(a0)+ | Store trap vector
458 adda.l #0x01000000,a1 | Increment trap #
459 dbf d1,binit1 | Loop until done
460
461 lea biosram,a0 | Clear BIOS ram ...
462 lea SSTACK-2,a1 | ... from biosram to SSTACK-1
463
464binit2: move.w #0,(a0)+ | Zero a word
465 cmpa.l a0,a1 | Last one ?
466 bne binit2 | Loop if not
467
468 move.l #rsarea,savptr | Setup pointer to register area
469 move.l #RSMAGIC,rsflag | Set magic in rsflag
470
471 move.l #nullrts,timevec | Set timer interrupt vector
472 move.l #nullrts,critvec | Set critical error vector
473 move.l #nullrts,termvec | Set process terminate vector
474 move.l #nullrts,resvec3 | Set software vector 3
475 move.l #nullrts,resvec4 | Set software vector 4
476 move.l #nullrts,resvec5 | Set software vector 5
477 move.l #nullrts,resvec6 | Set software vector 6
478 move.l #nullrts,resvec7 | Set software vector 7
479
480 move.l #hardhlt,0x0008 | Set bus error vector
481 move.l #nullrte,0x0014 | Set divide error vector
482 move.l #nullrte,0x0018 | Set CHK vector
483 move.l #nullrte,0x001C | Set TRAPV vector
484 move.l #nullrte,0x0024 | Set trace vector
485
486 move.l #nullrte,0x0030 | Set reserved vector 12
487 move.l #nullrte,0x0034 | Set reserved vector 13
488 move.l #nullrte,0x0038 | Set reserved vector 14
489
490 move.l #nullrte,0x003C | Set uninitialized int. vector
491
492 move.l #nullrte,0x0040 | Set reserved vector 16
493 move.l #nullrte,0x0044 | Set reserved vector 17
494 move.l #nullrte,0x0048 | Set reserved vector 18
495 move.l #nullrte,0x004C | Set reserved vector 19
496 move.l #nullrte,0x0050 | Set reserved vector 20
497 move.l #nullrte,0x0054 | Set reserved vector 21
498 move.l #nullrte,0x0058 | Set reserved vector 22
499 move.l #nullrte,0x005C | Set reserved vector 23
500
501 move.l #nullrte,0x0060 | Set spurious int. vector
502
503 move.l #serintr,0x0074 | Set ACIA interrupt vector
504 move.l #nullrte,0x0078 | Set level 6 vector
505 move.l #nullrte,0x007C | Set level 7 vector
506
507 move.l #trap13_,0x00B4 | Set trap13 vector
508 move.l #trap14_,0x00B8 | Set trap14 vector
509
510 .page
511
512 .ifne BUCHLA
513
514 move.l #nullfpu,0x0068 | Set FPU interrupt vector
515 move.l #api_int,0x006C | Set analog trap vector
516 move.l #timeint,0x0070 | Set timer trap vector
517
518 move.l #hdvini,hdv_init | Set disk init vector
519 move.l #getbpb,hdv_bpb | Set get BPB vector
520 move.l #rwabs,hdv_rw | Set disk I/O vector
521 move.l #bootload,hdv_boot | Setup boot load vector
522 move.l #mediach,hdv_mchg | Setup media change vector
523
524 move.w #0xFFFF,fverify | Set read after write flag
525 move.w #FL_SKR,seekrate | Set default seek rate
526 move.w #0xFFFF,booted | Say we're not booted yet
527 move.l #buffer,dskbufp | Setup default disk buffer
528
529 .page
530
531 move.b #7,PSG_WL | Select PSG R7
532 move.b #0x80,PSG_WD | Write 0x80 (port B = output)
533 move.b #15,PSG_WL | Select PSG R15
534 move.b #0x00,PSG_WD | Write 0x00 (sync enable)
535
536 move.b #0x00,TIME_T1H | Setup timer 1 (PLL)
537 move.b #0x1F,TIME_T1L | ... for divide by 64
538 move.b #0x0C,TIME_T2H | Setup timer 2 (FC)
539 move.b #0x7F,TIME_T2L | ... for divide by 3200
540 move.b #0x03,TIME_T3H | Setup timer 3 (RTC)
541 move.b #0x20,TIME_T3L | ... for 1Ms interval
542 move.b #0x42,TIME_CRX | Setup CR3
543 move.b #0x41,TIME_CR2 | Setup CR2
544 move.b #0x81,TIME_CRX | Setup CR1
545 move.b #0x80,TIME_CRX | Start the timers
546
547 .endc
548
549 lea sr1iorec,a0 | Serial-1 iorec address to a0
550 lea SR1ACIA,a1 | Serial-1 ACIA address to a1
551 lea sr1dflt,a2 | Serial-1 dflt table addr to a2
552 bsr.w aciainit | Go initialize the port
553
554 lea sr2iorec,a0 | Serial-2 iorec address to a0
555 lea SR2ACIA,a1 | Serial-2 ACIA address to a1
556 lea sr2dflt,a2 | Serial-2 dflt table addr to a2
557 bsr.w aciainit | Go initialize the port
558
559 .ifne BUCHLA
560
561 lea mc1iorec,a0 | MIDI-1 iorec address to a0
562 lea MC1ACIA,a1 | MIDI-1 ACIA address to a1
563 lea mc1dflt,a2 | MIDI-1 dflt table addr to a2
564 bsr.w aciainit | Go initialize the port
565
566 lea mc2iorec,a0 | MIDI-2 iorec address to a0
567 lea MC2ACIA,a1 | MIDI-2 ACIA address to a1
568 lea mc2dflt,a2 | MIDI-2 dflt table addr to a2
569 bsr.w aciainit | Go initialize the port
570
571 .page
572
573 lea VSDDINIT,a1 | Setup to load VSDD regs
574 lea vsddtab,a0 | ... from vsddtab
575 move.w #15,d0 | ... all 16 registers
576
577vsddinit: move.w (a0)+,(a1)+ | Load the VSDD registers
578 btst.l #0,d0
579 btst.l #0,d0
580 btst.l #0,d0
581 dbf d0,vsddinit
582
583 move.w vsddit02,VSDDINIT | Enable the video
584
585 move.l #api_fum,api_fi | Clear analog processor fifo
586 move.l #api_fum,api_fo | ...
587
588 move.w #23,d0 | Setup to clear key LEDs
589 move.b #0x80,d1 | ...
590
591ledclear: move.b d1,LEDS | Clear a LED
592 addq.b #1,d1 | Increment LED number
593 dbra d0,ledclear | Loop until all are done
594
595 move.w #7,d0 | Setup to clear pot LEDs
596 move.b #0x18,d1 | ...
597
598ledclr2: move.b d1,LEDS | Clear a LED
599 addq.b #1,d1 | Increment LED number
600 dbra d0,ledclr2 | Loop until all are done
601
602 clr.w fc_sw | Stop the frame clock
603 clr.l fc_val | ... and reset it
604
605 .page
606
607 lea FPUBASE+FPU_CTL,a0 | Point at FPU master level
608 move.w #0x0000,0x08(a0) | Set CV1 to 0
609 addq.w #1,d0 | Delay
610 addq.w #1,d0 | ...
611 move.w #0x0000,0x0A(a0) | Set SF1 to 0
612 addq.w #1,d0 | Delay
613 addq.w #1,d0 | ...
614 move.w #0x0000,0x0C(a0) | Set CV2 to 0
615 addq.w #1,d0 | Delay
616 addq.w #1,d0 | ...
617 move.w #0x0000,0x0E(a0) | Set SF2 to 0
618 addq.w #1,d0 | Delay
619 addq.w #1,d0 | ...
620 move.w #0x0000,0x10(a0) | Set CV3 to 0
621 addq.w #1,d0 | Delay
622 addq.w #1,d0 | ...
623 move.w #0x0000,0x12(a0) | Set SF3 to 0
624 addq.w #1,d0 | Delay
625 addq.w #1,d0 | ...
626 move.w #0x8300,0x02(a0) | Set new value '10' to -10.00
627 addq.w #1,d0 | Delay
628 addq.w #1,d0 | ...
629 move.w #0x8300,0x1C(a0) | Set new value '01' to -10.00
630 addq.w #1,d0 | Delay
631 addq.w #1,d0 | ...
632 move.w #0x0001,0x16(a0) | Set exponent for shortest time
633 addq.w #1,d0 | Delay
634 addq.w #1,d0 | ...
635 move.w #0xFFF0,0x14(a0) | Set mantissa for shortest time
636 addq.w #1,d0 | Delay
637 addq.w #1,d0 | ...
638 move.w #0x0005,0x00(a0) | Send control word to FPU
639
640 .endc
641
642 .page
643
644 move.w #INITIPL,sr | Enable interrupts
645 lea basepage,a1 | Pass start_ a pseudo base page
646 move.l #errno,p_bbase(a1) | ...
647 clr.l p_blen(a1) | ...
648 move.l a1,-(a7) | ...
649 jsr start_ | Go start ROMP (we assume ...)
650
651 jmp biosinit | Just in case we return ...
652
653 .page
654
655 .ifne BUCHLA
656
657| nullfpu -- Null FPU trap handler
658| ------- ---------------------
659nullfpu: movem.l d0-d0/a0-a0,-(a7) | Save registers
660 movea.l #FPUBASE,a0 | Setup FPU base address in a0
661 move.w FPU_IN(a0),d0 | Read FPU interrupt port
662 andi.l #0x000000FF,d0 | Mask for voice & parameter
663 lsl.l #5,d0 | Shift for word offset
664 addi.l #FPU_CTL,d0 | Add FPU control offset
665 move.w #FPU_RST,0(a0,d0.L) | Reset the function
666 clr.w FPU_CLR(a0) | Clear the interrupt
667 movem.l (a7)+,d0-d0/a0-a0 | Restore registers
668 rte | Return to interrupted code
669
670 .endc
671
672 .page
673
674| hardhlt -- Bus error trap handler
675| ------- ----------------------
676hardhlt: stop #0x2700 | stop dead -- system is AFU
677 bra hardhlt | ...
678
679| badtrap -- Bad trap handler
680| ------- ----------------
681badtrap: move.w (a7)+,crshsr | Get crash SR
682 move.l (a7)+,crshpc | Get crash PC
683 move.l a7,crshsp | Get crash SP
684 bsr badtr1 | Get TRAP PC with vector number
685 nop
686
687badtr1: move.l (a7)+,crshvc | Save for analysis of vector #
688 movem.l d0-d7/a0-a7,crshrg | Save crash registers
689 move.l usp,a0 | Preserve crash USP
690 move.l a0,crshus | ...
691 move.l a7,d0 | Get SP
692 andi.l #0xFFFFFFFE,d0 | ... make sure it's even
693 movea.l d0,a1 | ...
694 move.w #15,d0 | Save top 16 words
695 lea crshst,a0 | ... of crash stack in crshst
696
697badtr2: move.w (a1)+,(a0)+ | Save a stack value
698 dbf d0,badtr2 | Loop until all are saved
699
700 clr.l d0 | Get TRAP number
701 move.b crshvc,d0 | ... as LS byte of d0
702 move.l crshpc,a0 | Save crash PC in a0
703 move.w #0xFFFF,wzcrsh | Indicate we crashed
704 move.l #rsarea,savptr | Restore system save pointer
705 move.l #SSTACK,a7 | Reset the stack pointer
706 move.l #RSMAGIC,rsflag | ... and the stack sentinel
707 trap #15 | TRAP to ROMP
708
709 jmp biosinit | Recover with a cold start
710
711 .page
712
713 .ifne BUCHLA
714
715| timeint -- Timer interrupt handler
716| ------- -----------------------
717timeint: movem.l d0-d7/a0-a6,-(a7) | Save registers
718 move.b TIME_CR2,d0 | Get timer interrupt status
719 btst.l #2,d0 | Check timer 3 status
720 beq tmi02 | Jump if not active
721
722 move.b TIME_T3H,d1 | Read timer 1 count
723 lsl.l #8,d1 | ...
724 move.b TIME_T3L,d1 | ...
725 move.w d1,t3count | ... and save it
726
727 addq.l #1,hz_1k | Update 1ms clock (1 KHz)
728
729 move.w tdiv1,d1 | Update divider
730 addq.w #1,d1 | ...
731 move.w d1,tdiv1 | ...
732
733 cmpi.w #5,d1 | Do we need to update hz_200 ?
734 blt tmi02 | Jump if not
735
736 addq.l #1,hz_200 | Update 5ms clock (200 Hz)
737
738 move.w tdiv2,d1 | Update divider
739 addq.w #1,d1 | ...
740 move.w d1,tdiv2 | ...
741
742 cmpi.w #4,d1 | Do we need to update frclock ?
743 blt tmi01 | Jump if not
744
745 addq.l #1,frclock | Update 20 Ms clock (50 Hz)
746 tst.w flock | See if floppy is active
747 bne tmi00 | Don't call flopvbl if so
748
749 bsr flopvbl | Check on the floppy
750
751tmi00: move.w #0,tdiv2 | Reset tdiv2
752
753tmi01: move.w #0,tdiv1 | Reset tdiv1
754
755 .page
756
757tmi02: btst.l #0,d0 | Check timer 1 int
758 beq tmi03 | Jump if not set
759
760 move.b TIME_T1H,d1 | Read timer 1 to clear int.
761 lsl.l #8,d1 | ...
762 move.b TIME_T1L,d1 | ...
763 move.w d1,t1count | ... and save the count
764
765tmi03: btst.l #1,d0 | Check for timer 2 int.
766 beq tmi04 | Jump if not set
767
768 move.b TIME_T2H,d1 | Read timer 2 to clear int.
769 lsl.l #8,d1 | ...
770 move.b TIME_T2L,d1 | ...
771 move.w d1,t2count | ... and save the count
772
773 tst.w fc_sw | Should we update the frame ?
774 beq tmi04 | Jump if not
775
776 bmi tmi05 | Jump if we count down
777
778 move.l fc_val,d0 | Get the frame count
779 cmp.l #FCMAX,d0 | See it we've topped out
780 bge tmi06 | Jump if limit was hit
781
782 addq.l #1,d0 | Count up 1 frame
783 move.l d0,fc_val | Store updated frame count
784 bra tmi04 | Done
785
786tmi06: move.l #FCMAX,fc_val | Force hard limit, just in case
787 bra tmi04 | Done
788
789tmi05: move.l fc_val,d0 | Get the frame count
790 beq tmi04 | Done if already zero
791
792 subq.l #1,d0 | Count down 1 frame
793 move.l d0,fc_val | Store udpated frame count
794
795 movea.l timevec,a0 | Do RTC vector
796 move.w #1,-(a7) | ... pass 1 msec on stack
797 jsr (a0) | ...
798 addq.l #4,a7 | ...
799
800tmi04: movem.l (a7)+,d0-d7/a0-a6 | Restore registers
801 rte | Return to interrupted code
802
803 .endc
804
805 .page
806
807| trap14_ -- Extended BIOS entry point
808| ------- -------------------------
809trap14_: lea t14tab,a0 | Setup trap 14 table address
810 bra trapent | Go process trap
811
812| trap13_ -- Main BIOS entry point
813| ------- ---------------------
814trap13_: lea t13tab,a0 | Setup trap 13 table address
815
816trapent: move.l savptr,a1 | Get save area pointer
817 move.w (a7)+,d0 | Status register to D0
818 move.w d0,-(a1) | Save in save area
819 move.l (a7)+,-(a1) | Stash PC in save area
820 movem.l d3-d7/a3-a7,-(a1) | Save parameter register
821 move.l a1,savptr | Update save pointer
822 btst #13,d0 | Were we in sup. mode ?
823 bne trwzsup | Jump if so
824
825 move.l usp,a7 | Move user sp to stack ptr.
826
827trwzsup: move.w (a7)+,d0 | Get function number from stack
828 cmp.w (a0)+,d0 | Check against limit
829 bge trpexit | Jump if it's invalid
830
831 lsl.w #2,d0 | Multiply by 4 for use as index
832 move.l 0(a0,d0),d0 | Get routine address
833 move.l d0,a0 | ... into a0
834 bpl trpnind | Jump if it's indirect
835
836 move.l (a0),a0 | Use indirect value
837
838trpnind: sub.l a5,a5 | Clear a5
839 jsr (a0) | Execute the routine
840
841trpexit: move.l savptr,a1 | Get SAVPTR into a1
842 movem.l (a1)+,d3-d7/a3-a7 | Restore registers
843 move.l (a1)+,-(a7) | Push return onto stack
844 move.w (a1)+,-(a7) | Push status onto stack
845 move.l a1,savptr | Update SAVPTR
846
847| nullrte -- null rte
848| ------- --------
849nullrte: rte | Return to interrupted code
850
851| nullrts -- null return
852| ------- -----------
853nullrts: rts | Just return to the caller
854
855 .page
856
857| bconstat -- Get character device input status
858| -------- ---------------------------------
859bconstat: lea cdt01,a0 | Point at status table
860 bra condisp | Jump to dispatcher
861
862| bconin -- Get input from character device
863| ------ -------------------------------
864bconin: lea cdt02,a0 | Point at input table
865 bra condisp | Jump to dispatcher
866
867| bconout -- Output to character device
868| ------- --------------------------
869bconout: lea cdt03,a0 | Point at output table
870 bra condisp | Jump to dispatcher
871
872| bcostat -- Get character device output status
873| ------- ----------------------------------
874bcostat: lea cdt04,a0 | Point at status table
875
876| condisp -- Character device function dispatcher
877| ------- ------------------------------------
878condisp: move.w 4(a7),d0 | Get device number
879 lsl.w #2,d0 | ... times 4 for pointer
880 move.l 0(a0,d0),a0 | Get routine address
881 jmp (a0) | Jump to it
882
883 .page
884
885| sr1ist -- Check CON (Serial-1) input buffer status
886| ------ ----------------------------------------
887sr1ist: lea sr1iorec,a0 | Address of iorec to a0
888 lea SR1ACIA,a1 | Address of ACIA to a1
889 bra chkist | Go check buffer status
890
891| sr2ist -- Check AUX (Serial-2) input buffer status
892| ------ ----------------------------------------
893sr2ist: lea sr2iorec,a0 | Address of iorec to a0
894 lea SR2ACIA,a1 | Address of ACIA to a1
895
896 .ifne BUCHLA
897
898 bra chkist | Go check buffer status
899
900| mc1ist -- Check MC1 (MIDI-1) input buffer status
901| ------ --------------------------------------
902mc1ist: lea mc1iorec,a0 | Address of iorec to a0
903 lea MC1ACIA,a1 | Address of ACIA to a1
904 bra chkist | Go check buffer status
905
906| mc2ist -- Check MC2 (MIDI-2) input buffer status
907| ------ --------------------------------------
908mc2ist: lea mc2iorec,a0 | Address of iorec to a0
909 lea MC2ACIA,a1 | Address of ACIA to a1
910
911 .endc
912
913| chkist -- Check input buffer status
914| ------ -------------------------
915chkist: moveq.l #-1,d0 | Default to "Input available"
916 lea ibufhd(a0),a2 | Head index to a2
917 lea ibuftl(a0),a3 | Tail index to a3
918 cmpm.w (a3)+,(a2)+ | Buffer clear ?
919 bne chkist1 | Jump if not
920
921 moveq.l #0,d0 | Set to "Buffer empty"
922
923chkist1: rts | Return to caller
924
925 .page
926
927| sr1ost -- Check CON (Serial-1) output buffer status
928| ------ -----------------------------------------
929sr1ost: lea sr1iorec,a0 | Address of iorec to a0
930 bra chkost | Go check buffer status
931
932| sr2ost -- Check AUX (Serial-2) output buffer status
933| ------ -----------------------------------------
934sr2ost: lea sr2iorec,a0 | Address of iorec to a0
935
936 .ifne BUCHLA
937
938 bra chkost | Go check buffer status
939
940| mc1ost -- Check MC1 (MIDI-1) output buffer status
941| ------ ---------------------------------------
942mc1ost: lea mc1iorec,a0 | Address of iorec to a0
943 bra chkost | Go check buffer status
944
945| mc2ost -- Check MC2 (MIDI-2) output buffer status
946| ------ ---------------------------------------
947mc2ost: lea mc2iorec,a0 | Address of iorec to a0
948
949 .endc
950
951| chkost -- Check output buffer status
952| ------ --------------------------
953chkost: moveq.l #-1,d0 | Default to "Output OK"
954 move.w obuftl(a0),d2 | Tail index to d2
955 bsr wrapout | Test for pointer wraparound
956 cmp.w obufhd(a0),d2 | Compare with head index
957 bne chkost1 | Jump if not equal
958
959 moveq.l #0,d0 | Set to "Buffer full"
960
961chkost1: rts | Return to caller
962
963 .page
964
965| wrapin -- Check input pointer for wraparound
966| ------ ----------------------------------
967wrapin: add.w #1,d1 | Head index +1
968 cmp.w ibufsize(a0),d1 | = buffer size ?
969 bcs wrapin1 | Jump if not
970
971 moveq.l #0,d1 | Wraparound
972
973wrapin1: rts | Return to caller
974
975| wrapout -- Check output pointer for wraparound
976| ------- -----------------------------------
977wrapout: addq.w #1,d2 | Tail index +1
978 cmp.w obufsize(a0),d2 | = buffer size ?
979 bcs wrapout1 | Jump if not
980
981 moveq.l #0,d2 | Wrap around if so
982
983wrapout1: rts | Return to caller
984
985 .page
986
987| sr1inp -- Get input from Serial-1 (wait on busy)
988| ------ ---------------------------------------
989sr1inp: lea sr1iorec,a0 | Serial-1 iorec address
990 lea SR1ACIA,a1 | Serial-1 ACIA base
991 bra serinp | Go get a byte
992
993| sr2inp -- Get input from Serial-2 (wait on busy)
994| ------ ---------------------------------------
995sr2inp: lea sr2iorec,a0 | Serial-2 iorec address
996 lea SR2ACIA,a1 | Serial-2 ACIA base
997
998| serinp -- Get a byte from a serial port (with handshaking)
999| ------ -------------------------------------------------
1000serinp: bsr chkist | Check input status
1001 tst.w d0 | Character ready ?
1002 beq serinp | Loop until one is ...
1003
1004 bsr getser | Get a byte from the buffer
1005 and.w #0xFFFF,d0 | Isolate LS bits 7..0
1006 rts | Return to caller
1007
1008 .page
1009
1010 .ifne BUCHLA
1011
1012| mc1inp -- Get input from MIDI-1 (wait on busy)
1013| ------ -------------------------------------
1014mc1inp: lea mc1iorec,a0 | MIDI-1 iorec address
1015 lea MC1ACIA,a1 | MIDI-1 ACIA base
1016 bra midinp | Go get a byte
1017
1018| mc2inp -- Get input from MIDI-2 (wait on busy)
1019| ------ -------------------------------------
1020mc2inp: lea mc2iorec,a0 | MIDI-2 iorec address
1021 lea MC2ACIA,a1 | MIDI-2 ACIA base
1022
1023| midinp -- Get input from a MIDI port (no handshaking)
1024| ------ --------------------------------------------
1025midinp: bsr chkist | Check input status
1026 tst.w d0 | Character ready ?
1027 beq midinp | Loop until one is ...
1028
1029 move.w sr,-(a7) | Save status register
1030 ori.w #IPL7,sr | Set IPL = 7 (disable ints)
1031 move.w ibufhd(a0),d1 | Head index to d1
1032 cmp.w ibuftl(a0),d1 | Compare to tail index
1033 beq midin_1 | Jump if (somehow) empty
1034
1035 addq.w #1,d1 | Increment head index
1036 cmp.w ibufsize(a0),d1 | Did pointer wrap around ?
1037 bcs midin_2 | Jump if not
1038
1039 moveq.l #0,d1 | Wraparound
1040
1041midin_2: move.l ibuf(a0),a2 | Get buffer base address in a2
1042 moveq.l #0,d0 | Clear MS bits of d0
1043 move.b 0(a2,d1),d0 | Get character from buffer
1044 move.w d1,ibufhd(a0) | Update buffer head index
1045
1046midin_1: move.w (a7)+,sr | Restore status
1047 rts | Return to caller
1048
1049 .endc
1050
1051 .page
1052
1053| getser -- Get a byte from a serial port buffer (with handshaking)
1054| ------ --------------------------------------------------------
1055getser: move.w sr,-(a7) | Save status register
1056 ori.w #IPL7,sr | Set IPL = 7 (disable ints)
1057 move.w ibufhd(a0),d1 | Get input buffer head index
1058 cmp.w ibuftl(a0),d1 | Compare tail index
1059 beq rs_mt | Jump if buffer empty
1060
1061 bsr wrapin | Adjust pointer for wraparound
1062 move.l ibuf(a0),a2 | Get buffer address
1063 moveq.l #0,d0 | Clear out MS bits of d0
1064 move.b 0(a2,d1),d0 | Get character from buffer
1065 move.w d1,ibufhd(a0) | Update head index
1066 move.w (a7)+,sr | Restore status
1067 andi #0xFFFE,sr | Clear carry = OK
1068 bra rs_xnf | Go do XON/XOFF check
1069
1070rs_mt: move.w (a7)+,sr | Restore status
1071 ori #0x0001,sr | Set carry = no character there
1072
1073rs_xnf: btst #0,linedisc(a0) | Check for XON/XOFF mode
1074 beq rs_exit | Jump if not enabled
1075
1076 tst.b flagxon(a0) | XON active ?
1077 beq rs_exit | Jump if not
1078
1079 bsr rsilen | Get length of buffer used
1080 cmp.w ibuflow(a0),d2 | At low water mark ?
1081 bne rs_exit | Jump if not
1082
1083 move.b #0x11,d1 | Send an XON
1084 bsr serput | ...
1085 clr.b flagxon(a0) | Clear XON flag
1086
1087rs_exit: rts | Return to caller
1088
1089 .page
1090
1091| sr1out -- Output to serial-1
1092| ------ ------------------
1093sr1out: lea sr1iorec,a0 | Serial-1 iorec address to a0
1094 lea SR1ACIA,a1 | Serial-1 ACIA address to a1
1095 move.w 6(a7),d1 | Get data byte from stack
1096 bsr serput | Attempt to output
1097 bcs sr1out | Try until it works ...
1098
1099 rts | Return to caller
1100
1101| sr2out -- Output to Serial-2
1102| ------ ------------------
1103sr2out: lea sr2iorec,a0 | Serial-2 iorec address to a0
1104 lea SR2ACIA,a1 | Serial-2 ACIA address to a1
1105 move.w 6(a7),d1 | Get data byte from stack
1106 bsr serput | Attempt to output
1107 bcs sr2out | Try until it works ...
1108
1109 rts | Return to caller
1110
1111 .ifne BUCHLA
1112
1113| mc1out -- Output to MIDI-1
1114| ------ ----------------
1115mc1out: lea mc1iorec,a0 | MIDI-1 iorec address to a0
1116 lea MC1ACIA,a1 | MIDI-1 ACIA address to a1
1117 move.w 6(a7),d1 | Get data byte from stack
1118 bsr midput | Attempt to output
1119 bcs mc1out | Try until it works ...
1120
1121 rts | Return to caller
1122
1123| mc2out -- Output to MIDI-2
1124| ------ ----------------
1125mc2out: lea mc2iorec,a0 | MIDI-2 iorec address to a0
1126 lea MC2ACIA,a1 | MIDI-2 ACIA address to a1
1127 move.w 6(a7),d1 | Get data byte from stack
1128 bsr midput | Attempt to output
1129 bcs mc2out | Try until it works ...
1130
1131 rts | Return to caller
1132
1133 .endc
1134
1135 .page
1136
1137| serput -- Output a character to a serial port
1138| ------ -----------------------------------
1139serput: move.w sr,-(a7) | Save status register
1140 ori.w #IPL7,sr | Set IPL = 7 (disable ints)
1141 move.b ACIA_ISR(a1),isr(a0) | Get ACIA isr
1142 move.b ACIA_CSR(a1),csr(a0) | Get ACIA csr
1143 btst #0,linedisc(a0) | XON/XOFF mode ?
1144 beq serpt_1 | Jump if not
1145
1146 tst.b flagxoff(a0) | XON active ?
1147 bne serpt_2 | Jump if so
1148
1149serpt_1: btst.b #6,isr(a0) | Is ACIA still sending ?
1150 beq serpt_2 | Jump if so
1151
1152 move.w obufhd(a0),d2 | Head index to d2
1153 cmp.w obuftl(a0),d2 | Compare to tail index
1154 bne serpt_2 | Jump if buffer not empty
1155
1156 move.b d1,ACIA_TDR(a1) | Give byte to ACIA to send
1157 bra serpt_3 | Go deal with RTS/CTS if needed
1158
1159serpt_2: move.w obuftl(a0),d2 | Tail index to d2
1160 bsr wrapout | Adjust for wraparound
1161 cmp.w obufhd(a0),d2 | Compare to head index
1162 beq serpt_4 | Jump if buffer full
1163
1164 move.l obuf(a0),a2 | Get buffer base address in a2
1165 move.b d1,0(a2,d2) | Put character in buffer
1166 move.w d2,obuftl(a0) | Update buffer tail index
1167
1168serpt_3: bsr serchk | Check status on our way out
1169 bsr rtschk | Handle RTS protocol
1170 move.w (a7)+,sr | Restore status register
1171 andi #0xFFFE,sr | Clear carry flag = OK
1172 rts | Return to caller
1173
1174serpt_4: bsr serchk | Check status on our way out
1175 bsr rtschk | Handle RTS protocol
1176 move.w (a7)+,sr | Restore status register
1177 ori #0x0001,sr | Set carry flag = buffer full
1178 rts | Return to caller
1179
1180 .page
1181
1182 .ifne BUCHLA
1183
1184| midput -- Output to MIDI
1185| ------ --------------
1186midput: move.w sr,-(a7) | Save status register
1187 ori.w #IPL7,sr | Set IPL = 7 (diable ints)
1188 move.b ACIA_ISR(a1),isr(a0) | Get ACIA isr
1189 move.b ACIA_CSR(a1),csr(a0) | Get ACIA csr
1190 btst.b #6,isr(a0) | Is ACIA still sending ?
1191 beq midpt_2 | Jump if so
1192
1193 move.w obufhd(a0),d2 | Head index to d2
1194 cmp.w obuftl(a0),d2 | Compare to tail index
1195 bne midpt_2 | Jump if buffer not empty
1196
1197 move.b d1,ACIA_TDR(a1) | Give byte to ACIA to send
1198 bra midpt_3 | Go set final status and exit
1199
1200midpt_2: move.w obuftl(a0),d2 | Tail index to d2
1201 bsr wrapout | Adjust for wraparound
1202 cmp.w obufhd(a0),d2 | Compare to head index
1203 beq midpt_4 | Jump if buffer full
1204
1205 move.l obuf(a0),a2 | Get buffer base address in a2
1206 move.b d1,0(a2,d2) | Put character in buffer
1207 move.w d2,obuftl(a0) | Update buffer tail index
1208
1209midpt_3: bsr midchk | Check status on our way out
1210 move.w (a7)+,sr | Restore status register
1211 andi #0xFFFE,sr | Clear carry flag = OK
1212 rts | Return to caller
1213
1214midpt_4: bsr midchk | Check status on our way out
1215 move.w (a7)+,sr | Restore status register
1216 ori #0x0001,sr | Set carry flag = buffer full
1217 rts | Return to caller
1218
1219 .endc
1220
1221 .page
1222
1223| rtschk -- Check RTS mode and turn on RTS if it's enabled
1224| ------ ----------------------------------------------
1225rtschk: btst #1,linedisc(a0) | RTS/CTS mode set ?
1226 beq rts_1 | Jump if not
1227
1228 bsr rtson | Turn on RTS
1229
1230rts_1: rts | Return to caller
1231
1232| rsilen -- Get length of portion of input buffer that's been used so far
1233| ------ -------------------------------------------------------------
1234rsilen: move.w ibuftl(a0),d2 | Tail index to d2
1235 move.w ibufhd(a0),d3 | Head index to d3
1236 cmp.w d3,d2 | Head > Tail ?
1237 bhi rsi_1 | Jump if not
1238
1239 add.w ibufsize(a0),d2 | Add buffer size to tail index
1240
1241rsi_1: sub.w d3,d2 | Length = (adjusted)Tail - Head
1242 rts | Return to caller
1243
1244| rtson -- Turn on RTS line
1245| ----- ----------------
1246rtson: move.b cfr1(a0),d0 | Pick up CFR1 image
1247 bclr #0,d0 | Turn on RTS line (active low)
1248 bset #7,d0 | Make sure MS bit is set
1249 move.b d0,cfr1(a0) | Update CFR1 image
1250 move.b d0,ACIA_CFR(a1) | Send CFR to hardware
1251 rts | Return to caller
1252
1253| rtsoff -- Turn off RTS line
1254| ------ -----------------
1255rtsoff: move.b cfr1(a0),d0 | Pick up CFR1 image
1256 bset #0,d0 | Turn off RTS line (active low)
1257 bset #7,d0 | Make sure MS bit is set
1258 move.b d0,cfr1(a0) | Update CFR1 image
1259 move.b d0,ACIA_CFR(a1) | Send CFR to hardware
1260 rts
1261
1262 .page
1263
1264| serintr -- Serial (Serial-1, Serial-2, MIDI-1, MIDI-2) interrupt handler
1265| ------- -------------------------------------------------------------
1266serintr: movem.l d0-d3/a0-a2,-(a7) | Save registers
1267 lea sr1iorec,a0 | Point at Serial-1 iorec
1268 lea SR1ACIA,a1 | Point at Serial-1 ACIA
1269 bsr serint | Go process (possible) int.
1270
1271 lea sr2iorec,a0 | Point at Serial-2 iorec
1272 lea SR2ACIA,a1 | Point at Serial-2 ACIA
1273 bsr serint | Go process (possible) int.
1274
1275 .ifne BUCHLA
1276
1277 lea mc1iorec,a0 | Point at MIDI-1 iorec
1278 lea MC1ACIA,a1 | Point at MIDI-1 ACIA
1279 bsr midint | Go process (possible) int.
1280
1281 lea mc2iorec,a0 | Point at MIDI-2 iorec
1282 lea MC2ACIA,a1 | Point at MIDI-2 ACIA
1283 bsr midint | Go process (possible) int.
1284
1285 .endc
1286
1287 movem.l (a7)+,d0-d3/a0-a2 | Restore registers
1288 rte | Return from exception
1289
1290 .page
1291
1292| serint -- Process an interrupt from Serial-1 or Serial-2
1293| ------ ----------------------------------------------
1294serint: move.b ACIA_ISR(a1),isr(a0) | Get and save ISR
1295 move.b ACIA_CSR(a1),csr(a0) | Get and save CSR
1296
1297 btst.b #7,isr(a0) | Was int for this device ?
1298 beq serintx | Jump if not
1299
1300serchk: btst.b #1,isr(a0) | FRM/OVR/BRK error ?
1301 bne sererr | Jump if so
1302
1303 btst.b #0,isr(a0) | Receiver interrupt ?
1304 bne serrx | Jump if so
1305
1306sertxq: btst.b #6,isr(a0) | Transmitter interrupt ?
1307 bne sertx | Jump if so
1308
1309serctq: btst.b #5,isr(a0) | CTS interrupt ?
1310 bne sercts | Jump if so
1311
1312serintx: rts | Return to caller
1313
1314sererr: addq.w #1,errct(a0) | Update error count
1315 move.b ACIA_RDR(a1),erbyte(a0) | Get error byte
1316 rts
1317
1318| Handle CTS interupt
1319
1320sercts: btst.b #1,linedisc(a0) | RTS/CTS mode ?
1321 beq serintx | Ignore if not
1322
1323 btst.b #5,csr(a0) | CTS set ?
1324 beq serintx | Ignore if not
1325
1326sercts1: btst.b #6,isr(a0) | TDRE set ?
1327 beq sercts1 | Loop until it is (!)
1328
1329 move.w obufhd(a0),d2 | Head index to d2
1330 cmp.w obuftl(a0),d2 | Compare to tail index
1331 beq serintx | Done if buffer empty
1332
1333 bsr.w wrapout | Adjust pointer for wraparound
1334 move.l obuf(a0),a2 | Get buffer base in a2
1335 move.b 0(a2,d2),ACIA_TDR(a1) | Send byte on its way
1336 move.w d2,obufhd(a0) | Save updated head index
1337 rts
1338
1339 .page
1340
1341| Handle receiver interrupt
1342
1343serrx: btst.b #1,linedisc(a0) | RTS/CTS mode set ?
1344 beq serrx1 | Jump if not
1345
1346 bsr.w rtsoff | Turn off RTS
1347
1348serrx1: move.b ACIA_RDR(a1),d0 | Read data from ACIA
1349 btst.b #1,linedisc(a0) | RTS/CTS mode set ?
1350 bne serrx3 | Jump if so
1351
1352 btst.b #0,linedisc(a0) | XON/XOFF mode set ?
1353 beq serrx3 | Jump if not
1354
1355 cmpi.b #0x11,d0 | Is this an XON ?
1356 bne serrx2 | Jump if not
1357
1358 move.b #0x00,flagxoff(a0) | Clear flagxoff
1359 bra sertxq | Done
1360
1361serrx2: cmpi.b #0x13,d0 | Is this an XOFF ?
1362 bne serrx3 | Jump if not
1363
1364 move.b #0xFF,flagxoff(a0) | Set flagxoff
1365 bra sertxq | Done
1366
1367serrx3: move.w ibuftl(a0),d1 | Get tail index in d1
1368 bsr.w wrapin | Adjust for wraparound
1369 cmp.w ibufhd(a0),d1 | Head = tail ?
1370 beq seribf | If so, we drop the character
1371
1372 move.l ibuf(a0),a2 | Get buffer address
1373 move.b d0,0(a2,d1) | Stash byte in buffer
1374 move.w d1,ibuftl(a0) | Save updated tail index
1375 bsr rsilen | Get length of buffer used
1376 cmp.w ibufhi(a0),d2 | Hit high water mark ?
1377 bne serrx4 | Jump if not
1378
1379 btst.b #1,linedisc(a0) | RTS/CTS mode set ?
1380 bne sertxq | Done if so
1381
1382 btst.b #0,linedisc(a0) | XON/XOFF mode set ?
1383 beq serrx4 | Jump if not
1384
1385 tst.b flagxon(a0) | XOFF already sent ?
1386 bne serrx4 | Jump if so
1387
1388 move.b #0xFF,flagxon(a0) | Set the flag
1389 move.b #0x13,d1 | Send an XOFF
1390 bsr.w serput | ...
1391
1392 .page
1393
1394serrx4: btst #1,linedisc(a0) | RTS/CTS mode set ?
1395 beq sertxq | Done if not
1396
1397 bsr rtson | Turn on RTS
1398 bra sertxq
1399
1400| Handle transmitter interrupt
1401
1402sertx: btst.b #1,linedisc(a0) | RTS/CTS mode set ?
1403 bne sertx2 | If so, go check CTS
1404
1405 btst.b #0,linedisc(a0) | XON/XOFF mode set ?
1406 beq sertx1 | Jump if not
1407
1408 tst.b flagxoff(a0) | Check flagxoff
1409 bne serctq | Done if set
1410
1411sertx1: move.w obufhd(a0),d2 | Head index to d2
1412 cmp.w obuftl(a0),d2 | Compare to tail index
1413 beq serctq | Done if buffer empty
1414
1415 bsr wrapout | Adjust pointer for wraparound
1416 move.l obuf(a0),a2 | Get buffer base address
1417 move.b 0(a2,d2),ACIA_TDR(a1) | Send byte on its way
1418 move.w d2,obufhd(a0) | Save updated head index
1419 bra serctq | Done
1420
1421sertx2: btst.b #5,csr(a0) | CTS set in csr ?
1422 beq serctq | If not, go check for CTS int
1423
1424 bra sertx1 | CTS was set, go transmit
1425
1426seribf: move.b d0,erbyte(a0) | Log dropped character
1427 addq.w #1,ibfct(a0) | ...
1428 bra sertxq | Go check Tx interrupt
1429
1430 .page
1431
1432 .ifne BUCHLA
1433
1434| midint -- Process an interrupt from MIDI-1 or MIDI-2
1435| ------ ------------------------------------------
1436midint: move.b ACIA_ISR(a1),isr(a0) | Get and save ISR
1437 move.b ACIA_CSR(a1),csr(a0) | Get and save CSR
1438
1439 btst.b #7,isr(a0) | Was int for this device ?
1440 beq midintx | Jump if not
1441
1442midchk: btst.b #1,isr(a0) | FRM/OVR/BRK error ?
1443 bne miderr | Jump if so
1444
1445 btst.b #0,isr(a0) | Receiver interrupt ?
1446 bne midrx | Jump if so
1447
1448midtxq: btst.b #6,isr(a0) | Transmitter interrupt ?
1449 bne midtx | Jump if so
1450
1451midintx: rts | Return to caller
1452
1453miderr: addq.w #1,errct(a0) | Update error count
1454 move.b ACIA_RDR(a1),erbyte(a0) | Get error byte
1455 rts
1456
1457| Handle receiver interrupt
1458
1459midrx: move.b ACIA_RDR(a1),d0 | Read data from ACIA
1460 move.w ibuftl(a0),d1 | Get tail index in d1
1461 bsr.w wrapin | Adjust for wraparound
1462 cmp.w ibufhd(a0),d1 | Head = tail ?
1463 beq midibf | If so, we drop the character
1464
1465 move.l ibuf(a0),a2 | Get buffer address
1466 move.b d0,0(a2,d1) | Stash byte in buffer
1467 move.w d1,ibuftl(a0) | Save updated tail index
1468 bra midtxq | Done (go check tx int)
1469
1470 .page
1471
1472| Handle transmitter interrupt
1473
1474midtx: move.w obufhd(a0),d2 | Head index to d2
1475 cmp.w obuftl(a0),d2 | Compare to tail index
1476 beq midintx | Done if buffer empty
1477
1478 bsr wrapout | Adjust pointer for wraparound
1479 move.l obuf(a0),a2 | Get buffer base address
1480 move.b 0(a2,d2),ACIA_TDR(a1) | Send byte on its way
1481 move.w d2,obufhd(a0) | Save updated head index
1482 bra midintx | Done
1483
1484midibf: move.b d0,erbyte(a0) | Log dropped character
1485 addq.w #1,ibfct(a0) | ...
1486 bra midtxq | Go check Tx interrupt
1487
1488 .endc
1489
1490 .page
1491
1492| setexec -- Set an exception vector
1493| ------- -----------------------
1494setexec: move.w 4(a7),d0 | Get vector number
1495 lsl.w #2,d0 | .. times 4
1496 sub.l a0,a0 | Clear a0
1497 lea 0(a0,d0),a0 | Get address of old vector
1498 move.l (a0),d0 | Move old vector to d0
1499 move.l 6(a7),d1 | Pick up new vector
1500 bmi setexec1 | Don't set if = -1
1501
1502 move.l d1,(a0) | Set new vector
1503
1504setexec1: rts | Return to caller
1505
1506| piorec -- Get pointer to iorec structure
1507| ------ ------------------------------
1508piorec: moveq.l #0,d1 | Clear out d1
1509 move.w 4(a7),d1 | Get device number
1510 move.w sr,-(a7) | Save status register
1511 ori.w #IPL7,sr | Set IPL = 7 (no ints)
1512 lea iortab,a2 | Get base address of table
1513 asl.l #2,d1 | Device # times 4 for index
1514 move.l 0(a2,d1),d0 | Get iorec address from table
1515 move.w (a7)+,sr | Restore status register
1516 rts | Return to caller
1517
1518 .page
1519
1520| setport -- Set ACIA parameters (unit, mode, baud, CFR0, CFR1)
1521| ------- ---------------------------------------------------
1522setport: moveq.l #0,d1 | Clear out d1
1523 move.w 4(a7),d1 | Get device number
1524 asl.l #3,d1 | Times 8 for index
1525 ori.w #IPL7,sr | Set IPL = 7 (no ints)
1526 lea aciatab,a2 | Get base of table
1527 move.l 0(a2,d1),d0 | Get iorec address
1528 move.l 4(a2,d1),d2 | Get ACIA address
1529 movea.l d0,a0 | Setup a0 = iorec address
1530 movea.l d2,a1 | Setup a1 = ACIA address
1531 tst.w 6(a7) | Change mode ?
1532 bmi setpt1 | Jump if not
1533
1534 move.b 7(a7),linedisc(a0) | Set line discipline (mode)
1535
1536setpt1: tst.w 8(a7) | Change baud rate ?
1537 bmi setpt2 | Jump if not
1538
1539 moveq.l #0,d1 | Clear out d1
1540 move.w 8(a7),d1 | Get baud rate index
1541 lea brtable,a2 | Get base of baud rate table
1542 move.b 0(a2,d1),d2 | Get baud rate code from table
1543 move.b cfr0(a0),d0 | Get current CFR0
1544 andi.w #0x0070,d0 | Mask off old baud rate code
1545 or.w d2,d0 | OR in new baud rate code
1546 move.b d0,cfr0(a0) | Update CFR0 in table
1547 move.b d0,ACIA_CFR(a1) | Update hardware
1548
1549setpt2: tst.w 10(a7) | Change CFR0 ?
1550 bmi setpt3 | Jump if not
1551
1552 move.b 11(a7),cfr0(a0) | Update CFR0 in table
1553 move.b cfr0(a0),ACIA_CFR(a1) | Update CFR0 in hardware
1554
1555setpt3: tst.w 12(a7) | Change CFR1 ?
1556 bmi setpt4 | Jump if not
1557
1558 bset.b #7,13(a7) | Force D7 = 1 in argument
1559 move.b 13(a7),cfr1(a0) | Update CFR1 in table
1560 move.b cfr1(a0),ACIA_CFR(a1) | Update CFR1 in hardware
1561
1562setpt4: rts | Return to caller
1563
1564 .page
1565
1566| aciainit -- Initialize an ACIA port
1567| -------- -----------------------
1568aciainit: move.w #IORECLN,d0 | Setup byte count for move
1569 move.l a0,-(a7) | Save iorec base
1570
1571aciai_1: move.b (a2)+,(a0)+ | Move the default to the iorec
1572 dbf d0,aciai_1 | ...
1573
1574 move.l (a7)+,a0 | Restore iorec base
1575 move.b cfr0(a0),ACIA_CFR(a1) | Setup CFR0
1576 move.b cfr1(a0),ACIA_CFR(a1) | Setup CFR1
1577 move.b ACIA_RDR(a1),d0 | Clear RDR
1578 move.b #0x7F,ACIA_IER(a1) | Disable all interrupts
1579 btst.b #1,linedisc(a0) | Are we in RTS/CTS mode ?
1580 bne aciai_2 | Jump if so
1581
1582 move.b #0xC3,ACIA_IER(a1) | Enable TDRE, RDRF
1583 bra aciai_3 | Go return
1584
1585aciai_2: move.b #0xE3,ACIA_IER(a1) | Enable interrupts we want
1586
1587aciai_3: rts | Return to caller
1588
1589 .page
1590
1591 .ifne BUCHLA
1592
1593| fastcopy -- Copy disk sector quickly
1594| -------- ------------------------
1595fastcopy: move.l 4(a7),a0 | Get source pointer
1596 move.l 8(a7),a1 | Get destination pointer
1597 move.w 0x3F,d0 | 512 bytes (63+1)*8
1598
1599fastcpy1: move.b (a0)+,(a1)+ | Move 8 bytes
1600 move.b (a0)+,(a1)+ | ...
1601 move.b (a0)+,(a1)+ | ...
1602 move.b (a0)+,(a1)+ | ...
1603 move.b (a0)+,(a1)+ | ...
1604 move.b (a0)+,(a1)+ | ...
1605 move.b (a0)+,(a1)+ | ...
1606 move.b (a0)+,(a1)+ | ...
1607 dbra d0,fastcpy1 | Loop until all bytes are moved
1608
1609 rts | Return to caller
1610
1611 .page
1612
1613| hdvini -- Drive initialization
1614| ------ --------------------
1615hdvini: link a6,#-18 | Reserve space on stack
1616 movem.l d3-d7/a3-a5,-(a7) | Preserve registers
1617 move.l #300,maxactim | maxactim = 300 * 20ms
1618 clr.w d0 | Put zeros in ...
1619 move.w d0,nflops | ... nflops
1620 move.w d0,dskmode | ... dskmode
1621 move.w d0,-2(a6) | Start with drive A
1622 bra hdvilp | ...
1623
1624hdvilp1: movea.l #dskmode,a0 | Get dskmode address in a0
1625 movea.w -2(a6),a1 | Drive number in a1
1626 adda.l a1,a0 | Point at dskmode for drive
1627 clr.b (a0) | Clear flag in dskmode
1628 clr.w -(a7) | Push arguments onto stack
1629 clr.w -(a7) | ...
1630 clr.w -(a7) | ...
1631 move.w -2(a6),-(a7) | Push drive number onto stack
1632 clr.l -(a7) | ... filler
1633 clr.l -(a7) | ... filler
1634 jsr flopini | Initialize drive
1635 adda.l #16,a7 | Cleanup stack
1636 move.w d0,-(a7) | Save error code on stack
1637 movea.w -2(a6),a0 | Get drive number
1638 adda.l a0,a0 | ... times 2
1639 adda.l #dskerrs,a0 | Add base of dskerrs
1640 move.w (a7)+,(a0) | Move error code off of stack
1641 bne hdvind | Jump if drive not present
1642
1643 addq.w #1,nflops | Update number of drives
1644 or.l #3,drvbits | Setup drive bits
1645
1646hdvind: addq.w #1,-2(a6) | Increment drive number
1647
1648hdvilp: cmp.w #2,-2(a6) | See if it's 2 yet
1649 blt hdvilp1 | Loop until it is
1650
1651 movem.l (a7)+,d3-d7/a3-a5 | Restore registers
1652 unlk a6 | Release temporary stack space
1653 rts | Return to caller
1654
1655| drvmap -- get drive map
1656| ------ -------------
1657drvmap: move.l drvbits,d0 | Get drive bits
1658 rts | Return to caller
1659
1660 .page
1661
1662| getbpb -- get BIOS parameter block
1663| ------ ------------------------
1664getbpb: link a6,#-12 | Reserve space for temporaries
1665 movem.l d5-d7/a4-a5,-(a7) | Save registers on stack
1666 cmp.w #2,8(a6) | Check drive number
1667 blt gbpb1 | Jump if OK
1668
1669 clr.l d0 | Set drive number to 0
1670 bra gbpber | Go flag error
1671
1672gbpb1: move.w 8(a6),d0 | Get drive number
1673 asl.w #5,d0 | ... times 32
1674 ext.l d0 | ... extend sign
1675 move.l d0,a5 | Move to a5
1676 add.l #drvbpbs,a5 | Add base of drive bpb are
1677 move.l a5,a4 | Save in a4
1678
1679gbpbrds: move.w #1,(a7) | floprd count = 1,
1680 clr.w -(a7) | ... side = 0,
1681 clr.w -(a7) | ... track = 0,
1682 move.w #1,-(a7) | ... sector = 1,
1683 move.w 8(a6),-(a7) | ... drive #,
1684 clr.l -(a7) | ... filler
1685 move.l #buffer,-(a7) | ... buffer address,
1686 jsr floprd | Go read the sector
1687 add.l #16,a7 | Cleanup stack
1688 move.l d0,-12(a6) | Save error code
1689 tst.l -12(a6) | ... and test it
1690 bge gbpb2 | Jump if OK
1691
1692 move.w 8(a6),(a7) | Put drive number on stack
1693 move.l -12(a6),d0 | Get error code
1694 move.w d0,-(a7) | ... and put it on the stack
1695 jsr criter | Go do critical error routine
1696 addq.l #2,a7 | Cleanup stack
1697 move.l d0,-12(a6) | Save error code
1698
1699gbpb2: move.l -12(a6),d0 | Get error code
1700 cmp.l #RETRYIT,d0 | Magic number for retry ?
1701 beq gbpbrds | Re-read if so
1702
1703 tst.l -12(a6) | Test error code
1704 bge gbpb3 | Jump if OK
1705
1706 clr.l d0 | Set code in d0
1707 bra gbpber | Go set error code
1708
1709 .page
1710
1711gbpb3: move.l #buffer+11,(a7) | Bytes per sector
1712 bsr itom | Convert 8086 to 68K format
1713 move.w d0,d7 | Save bytes per sector
1714 beq gbpb4 | Jump if zero
1715
1716 move.b buffer+13,d6 | Sectors per cluster
1717 ext.w d6 | ... sign extended
1718 and.w #0xFF,d6 | ... and trimmed
1719 bne gbpb5 | Jump if non-zero
1720
1721gbpb4: clr.l d0 | Set error code
1722 bra gbpber | ...
1723
1724gbpb5: move.w d7,(a4) | Set recsize
1725 move.w d6,2(a4) | Set clsiz
1726 move.l #buffer+22,(a7) | Convert sectors per fat
1727 bsr itom | ...
1728 move.w d0,8(a4) | Set fsiz
1729 move.w 8(a4),d0 | Get fsiz
1730 addq.w #1,d0 | ... plus 1
1731 move.w d0,10(a4) | Set fatrec
1732 move.w (a4),d0 | Get recsize
1733 muls.w 2(a4),d0 | ... times clsiz
1734 move.w d0,4(a4) | Set clsizb
1735 move.l #buffer+17,(a7) | Convert number of dir ents
1736 bsr itom | ...
1737 asl.w #5,d0 | ... times 32
1738 ext.l d0 | ... sign extended
1739 divs.w (a4),d0 | ... / recsize
1740 move.w d0,6(a4) | Set rdlen
1741 move.w 10(a4),d0 | Get fatrec
1742 add.w 6(a4),d0 | ... + rdlen
1743 add.w 8(a4),d0 | ... + fsiz
1744 move.w d0,12(a4) | Set datrec
1745 move.l #buffer+19,(a7) | Get number of sectors
1746 bsr itom | ... convert
1747 sub.w 12(a4),d0 | ... - datrec
1748 ext.l d0 | ... sign extended
1749 divs.w 2(a4),d0 | ... / clsiz
1750 move.w d0,14(a4) | Set numcl
1751
1752 .page
1753
1754 move.l #buffer+26,(a7) | Convert number of heads
1755 bsr itom | ...
1756 move.w d0,20(a5) | Set dnsides
1757 move.l #buffer+24,(a7) | Convert sectors per track
1758 bsr itom | ...
1759 move.w d0,24(a5) | Set dspt
1760 move.w 20(a5),d0 | Get dnsides
1761 muls.w 24(a5),d0 | ... * dspt
1762 move.w d0,22(a5) | Set dspc
1763 move.l #buffer+28,(a7) | Convert number of hidden sects
1764 bsr itom | ...
1765 move.w d0,26(a5) | Set dhidden
1766 move.l #buffer+19,(a7) | Convert sectors on disk
1767 bsr itom | ...
1768 ext.l d0 | ... sign extended
1769 divs.w 22(a5),d0 | ... / dspc
1770 move.w d0,18(a5) | Set dntracks
1771 clr.w d7 | Counter = 0
1772 bra gbpblpt | Jump to end of loop
1773
1774gbpb6: move.l a5,a0 | Get buffer pointer
1775 move.w d7,a1 | Loop count to a1
1776 add.l a1,a0 | ... + bpb address
1777 move.w d7,a1 | Loop count to a1
1778 add.l #buffer,a1 | ... + buffer address
1779 move.b 8(a1),28(a0) | Copy a s/n byte
1780 addq.w #1,d7 | Update loop count
1781
1782gbpblpt: cmp.w #3,d7 | Moved 3 bytes ?
1783 blt gbpb6 | Loop if not
1784
1785 .page
1786
1787 move.l #cdev,a0 | Address of cdev table
1788 move.w 8(a6),a1 | ... plus drive number
1789 add.l a1,a0 | ... to a0
1790 move.l #wpstatus,a1 | Address of wpstatus table
1791 move.w 8(a6),a2 | ... plus drive number
1792 add.l a2,a1 | ... to a1
1793 move.b (a1),(a0) | Move wpstatus to cdev
1794 beq gbpb7
1795
1796 moveq.l #1,d0 | Set status = "Uncertain"
1797 bra gbpb8
1798
1799gbpb7: clr.w d0 | Set status = "Unchanged"
1800
1801gbpb8: move.l #dskmode,a1 | Update dskmode table
1802 move.w 8(a6),a2 | ...
1803 add.l a2,a1 | ...
1804 move.b d0,(a1) | ...
1805 move.l a5,d0 | Setup to return bpb pointer
1806
1807gbpber: tst.l (a7)+ | Pop garbage off top of stack
1808 movem.l (a7)+,d6-d7/a4-a5 | Restore registers
1809 unlk a6
1810 rts
1811
1812 .page
1813
1814| mediach -- check for media change
1815| ------- ----------------------
1816mediach: link a6,#0 | Create scratch on stack
1817 movem.l d6-d7/a5,-(a7) | Save registers on stack
1818 cmp.w #2,8(a6) | Check drive number
1819 blt media1 | Jump if OK
1820
1821 moveq.l #ERR15,d0 | Error -- "unknown device"
1822 bra media2 | ...
1823
1824media1: move.w 8(a6),d7 | Get drive number in d7
1825 movea.w d7,a5 | Point into dskmode table
1826 add.l #dskmode,a5 | ...
1827 cmp.b #2,(a5) | Definitely changed ?
1828 bne media3 | Jump if not
1829
1830 moveq.l #2,d0 | Setup to return "Changed"
1831 bra media2 | Done -- go return to caller
1832
1833media3: move.l #wplatch,a0 | Check wplatch for drive
1834 tst.b 0(a0,d7) | ...
1835 beq media4 | Jump if not set
1836
1837 move.b #1,(a5) | Set dskmode to "Uncertain"
1838
1839media4: move.l hz_200,d0 | Get time in d0
1840 movea.w d7,a1 | Calculate acctim table address
1841 add.l a1,a1 | ... = drive # * 4
1842 add.l a1,a1 | ...
1843 add.l #acctim,a1 | ... + acctim base address
1844 move.l (a1),d1 | Get acctim for drive
1845 sub.l d1,d0 | Subtract from current time
1846 cmp.l maxactim,d0 | Timed out ?
1847 bge media5 | Jump if so
1848
1849 clr.w d0 | Setup to return "Unchanged"
1850 bra media2
1851
1852media5: move.b (a5),d0 | Return status from dskmode
1853 ext.w d0
1854
1855media2: tst.l (a7)+ | Pop extra stack word
1856 movem.l (a7)+,d7/a5 | Restore registers
1857 unlk a6
1858 rts | Return to caller
1859
1860 .page
1861
1862| rwabs -- read / write sector(s)
1863| ----- ----------------------
1864rwabs: link a6,#-4 | Reserve stack for temps
1865 movem.l d4-d7/a5,-(a7) | Save registers on stack
1866 cmp.w #2,18(a6) | Drive number
1867 blt rwabs1
1868
1869 moveq.l #ERR15,d0 | ERROR -- "unknown device"
1870 bra rwabser
1871
1872rwabs1: move.w 18(a6),d6 | Save drive number
1873 cmp.w #2,8(a6) | Check rwflag
1874 bge rwabs7
1875
1876 move.w d6,d0
1877 asl.w #5,d0
1878 ext.l d0
1879 move.l d0,a5
1880 add.l #drvbpbs,a5
1881 move.w d6,(a7)
1882 bsr mediach | Test for media change
1883 move.w d0,d7 | Save status
1884 cmp.w #2,d7 | Disk changed ?
1885 bne rwabs2 | Jump if not
1886
1887 moveq.l #ERR14,d0 | ERROR -- "media changed"
1888 bra rwabser | ...
1889
1890rwabs2: cmp.w #1,d7 | Disk possibly changed ?
1891 bne rwabs7
1892
1893rwabs3: move.w #1,(a7) | floprd count = 1,
1894 clr.w -(a7) | ... side = 0,
1895 clr.w -(a7) | ... track = 0,
1896 move.w #1,-(a7) | ... sector = 1,
1897 move.w d6,-(a7) | ... drive number,
1898 clr.l -(a7) | ... filler,
1899 move.l #buffer,-(a7) | ... buffer address,
1900 jsr floprd | Read boot sector
1901 add.l #16,a7 | Cleanup stack
1902 move.l d0,-4(a6) | Save error number
1903 tst.l -4(a6) | ... and test it
1904 bge rwabs11 | Jump if OK
1905
1906 .page
1907
1908 move.w d6,(a7)
1909 move.l -4(a6),d0
1910 move.w d0,-(a7)
1911 jsr criter | Call critical error code
1912 addq.l #2,a7 | Cleanup stack
1913 move.l d0,-4(a6)
1914
1915rwabs11: move.l -4(a6),d0
1916 cmp.l #RETRYIT,d0
1917 beq rwabs3 | Read again
1918
1919 tst.l -4(a6) | Test error number
1920 bge rwabs4 | OK ?
1921
1922 move.l -4(a6),d0
1923 bra rwabser | ERROR
1924
1925rwabs4: clr.w d7 | Clear media change status
1926 bra rwabs10
1927
1928rwabs6: move.l #buffer,a0 | Address of sector buffer to a0
1929 move.b 8(a0,d7),d0 | Serial number
1930 ext.w d0
1931 move.b 28(a5,d7),d1 | Compare to old one
1932 ext.w d1
1933 cmp.w d1,d0
1934 beq rwabs5 | Jump if they're the same
1935
1936 moveq.l #ERR14,d0 | ERROR -- "media changed"
1937 bra rwabser
1938
1939rwabs5: addq.w #1,d7 | Next byte of serial number
1940
1941rwabs10: cmp.w #3,d7 | All 3 bytes checked ?
1942 blt rwabs6 | Loop if not
1943
1944 .page
1945
1946 move.w d6,a0 | Point at wplatch for drive
1947 add.l #wplatch,a0 | ...
1948 move.w d6,a1 | Point at wpstatus for drive
1949 add.l #wpstatus,a1 | ...
1950 move.b (a1),(a0) | Move wpstatus to wplatch
1951 bne rwabs9 | Jump if set
1952
1953 move.w d6,a0 | Set dskmode to "Unchanged"
1954 add.l #dskmode,a0 | ...
1955 clr.b (a0) | ...
1956
1957rwabs7: tst.w nflops | Test nflops
1958 bne rwabs8
1959
1960 moveq.l #ERR02,d0 | ERROR -- "drive not ready"
1961 bra rwabser
1962
1963rwabs8: cmp.w #1,8(a6) | Check rwflag
1964 ble rwabs9
1965
1966 subq.w #2,8(a6) | Adjust to 0|1
1967
1968rwabs9: move.w 14(a6),(a7) | Setup count,
1969 move.w d6,-(a7) | ... drive,
1970 move.w 16(a6),-(a7) | ... recno,
1971 move.l 10(a6),-(a7) | ... buffer,
1972 move.w 8(a6),-(a7) | ... rwflag
1973 bsr floprw | Call floprw
1974
1975 add.l #10,a7 | Cleanup stack
1976
1977rwabser: tst.l (a7)+ | Pop stack scratch
1978 movem.l (a7)+,d5-d7/a5 | Restore registers
1979 unlk a6 | Release temporaries
1980 rts | Return to caller
1981
1982 .page
1983
1984| floprw -- Floppy read / write driver
1985| ------ --------------------------
1986floprw: link a6,#-6 | Reserve space for temps
1987 movem.l d2-d7/a5,-(a7) | Save registers
1988 move.w 16(a6),d0 | Drive number to d0
1989 asl.w #5,d0 | Shift ( *32 )
1990 ext.l d0 | Sign extend it, too
1991 move.l d0,a5 | Result in a5
1992 add.l #drvbpbs,a5 | Add base of BPB table
1993 btst #0,13(a6) | Buffer address even ?
1994 bne floprw01 | Jump if not
1995
1996 clr.w d0 | Clear odd flag
1997 bra floprw02 | Go save the flag
1998
1999floprw01: moveq.l #1,d0 | Set odd flag
2000
2001floprw02: move.w d0,-2(a6) | Save it
2002 tst.w 22(a5) | dspc set ?
2003 bne floprw20 | Jump if so
2004
2005 moveq.l #9,d0 | Assume 9
2006 move.w d0,22(a5) | ... and make it the default
2007 move.w d0,24(a5) | ... for dspt and dspc
2008
2009floprw20: bra floprw18
2010
2011floprw03: tst.w -2(a6) | Is odd flag set ?
2012 beq floprw04 | Jump if not
2013
2014 move.l #buffer,d0 | Point to sector buffer
2015 bra floprw05
2016
2017floprw04: move.l 10(a6),d0 | Get buffer address
2018
2019floprw05: move.l d0,-6(a6) | ... and save
2020 move.w 14(a6),d6 | Get recno (lsn)
2021 ext.l d6 | Extend it to long
2022 divs.w 22(a5),d6 | Divide by dspc for track #
2023 move.w 14(a6),d4 | Get recno
2024 ext.l d4 | Extend to long
2025 divs.w 22(a5),d4 | Divide by dspc
2026 swap d4 | Use remainder as sector number
2027 cmp.w 24(a5),d4 | Compare with dspt
2028 bge floprw06 | Greater than or equal ?
2029
2030 clr.l d5 | Use side 0
2031 bra floprw07
2032
2033floprw06: moveq.l #1,d5 | Use side 1
2034 sub.w 24(a5),d4 | Subtract dspt from sector #
2035
2036 .page
2037
2038floprw07: tst.w -2(a6) | Is odd flag set ?
2039 beq floprw08 | Jump if not
2040
2041 moveq.l #1,d3 | Set counter to 1
2042 bra floprw10
2043
2044floprw08: move.w 24(a5),d0 | Get dspt
2045 sub.w d4,d0 | Subtract sector number
2046 cmp.w 18(a6),d0 | Compare with number of sectors
2047 bge floprw09 | Jump if greater than or eq to
2048
2049 move.w 24(a5),d3 | Get dspt
2050 sub.w d4,d3 | Subtract sector number
2051 bra floprw10
2052
2053floprw09: move.w 18(a6),d3 | Count = number of sectors
2054
2055floprw10: addq.w #1,d4 | Adjust sector number (1 org)
2056
2057floprw11: tst.w 8(a6) | Test r/w flag
2058 beq floprw14 | Jump if it's a read
2059
2060 move.l -6(a6),d0 | Get buffer pointer
2061 cmp.l 10(a6),d0 | See if it's = buffer addr
2062 beq floprw12 | Jump if so
2063
2064 move.l -6(a6),(a7) | Get source address
2065 move.l 10(a6),-(a7) | Destination address
2066 jsr fastcopy | Copy the sector
2067 addq.l #4,a7 | Cleanup stack
2068
2069floprw12: move.w d3,(a7) | Number of sectors
2070 move.w d5,-(a7) | Side number
2071 move.w d6,-(a7) | Track number
2072 move.w d4,-(a7) | Sector number
2073 move.w 16(a6),-(a7) | Drive number
2074 clr.l -(a7) | Filler
2075 move.l -6(a6),-(a7) | Buffer address
2076 jsr flopwr | Write sector
2077 add.l #16,a7 | Cleaup stack
2078 move.l d0,d7 | Save error code in d7
2079 tst.l d7 | Errors ?
2080 bne floprw13 | Jump if so
2081
2082 .page
2083
2084 tst.w fverify | Verify after write ?
2085 beq floprw13 | Jump if not
2086
2087 move.w d3,(a7) | Number of sectors
2088 move.w d5,-(a7) | Side number
2089 move.w d6,-(a7) | Track number
2090 move.w d4,-(a7) | Sector number
2091 move.w 16(a6),-(a7) | Drive number
2092 clr.l -(a7) | Filler
2093 move.l #buffer,-(a7) | Buffer address
2094 jsr flopver | Verify sector(s)
2095 add.l #16,a7 | Cleanup stack
2096 move.l d0,d7 | Save error code in d7
2097 tst.l d7 | Errors ?
2098 bne floprw13 | Jump if so
2099
2100 move.l #buffer,(a7) | Address of sector buffer
2101 bsr itom | Convert first word of buffer
2102 tst.w d0 | Bad sectors ?
2103 beq floprw13 | Jump if not
2104
2105 moveq.l #ERR16,d7 | ERROR -- "Bad sectors"
2106
2107floprw13: bra floprw15
2108
2109 .page
2110
2111floprw14: move.w d3,(a7) | Number of sectors
2112 move.w d5,-(a7) | Side number
2113 move.w d6,-(a7) | Track number
2114 move.w d4,-(a7) | Sector number
2115 move.w 16(a6),-(a7) | Drive number
2116 clr.l -(a7) | Filler
2117 move.l -6(a6),-(a7) | Sector buffer
2118 jsr floprd | Read floppy sector(s)
2119 add.l #16,a7 | Cleanup stack
2120 move.l d0,d7 | Save error code in d7
2121 move.l -6(a6),d0 | User buffer address
2122 cmp.l 10(a6),d0 | Is it the desired buffer ?
2123 beq floprw15 | Jump if so
2124
2125 move.l 10(a6),(a7) | Push source address
2126 move.l -6(a6),-(a7) | Push destination address
2127 jsr fastcopy | Copy the sector
2128 addq.l #4,a7 | Cleanup stack
2129
2130floprw15: tst.l d7 | Error code set ?
2131 bge floprw16 | Jump if not
2132
2133 move.w 16(a6),(a7) | Push drive number
2134 move.l d7,d0 | Error code
2135 move.w d0,-(a7) | ... onto stack
2136 jsr criter | Call critical error handler
2137 addq.l #2,a7 | Cleanup stack
2138 move.l d0,d7 | Get error code
2139
2140floprw16: cmp.l #RETRYIT,d7 | Re-try ?
2141 beq floprw11 | Jump if so
2142
2143 tst.l d7 | Check error code
2144 bge floprw17 | Jump if no error
2145
2146 move.l d7,d0 | Error code is the result
2147 bra floprw19
2148
2149 .page
2150
2151floprw17: move.w d3,d0 | Sector counter to d0
2152 ext.l d0 | Sign extend
2153 moveq.l #9,d1 | Times 512
2154 asl.l d1,d0 | ...
2155 add.l d0,10(a6) | Update buffer address
2156 add.w d3,14(a6) | Update sector number
2157 sub.w d3,18(a6) | Update sector count
2158
2159floprw18: tst.w 18(a6) | More sectors ?
2160 bne floprw03 | Jump if so
2161
2162 clr.l d0 | Set "no error" as result
2163
2164floprw19: tst.l (a7)+ | Test top of stack
2165 movem.l (a7)+,d3-d7/a5 | Restore registers
2166 unlk a6 | Release stack space
2167 rts | Return to caller
2168
2169 .page
2170
2171| itom -- Convert 8086 integer format to 680000 integer format
2172| ---- ----------------------------------------------------
2173itom: link a6,#-4 | Reserve stack for temps
2174 move.l 8(a6),a0 | Address of the number to a0
2175 move.b 1(a0),d0 | Get high byte
2176 ext.w d0 | Make it a word
2177 and.w #0xFF,d0 | Isolate bits 0..7
2178 asl.w #8,d0 | Shift in bits 8..15
2179 move.l 8(a6),a1 | Address of the number to a1
2180 move.b (a1),d1 | Get low byte
2181 ext.w d1 | Extend to word
2182 and.w #0xFF,d1 | Isolate bits 0..7
2183 or.w d1,d0 | Combine with bits 8..15
2184 unlk a6 | Release stack space
2185 rts | Return to caller
2186
2187 .page
2188
2189| flopini -- Initialize floppy drive
2190| ------- -----------------------
2191flopini: lea dsb0,a1 | Point to dsb for drive A
2192 tst.w 12(a7) | Drive A wanted ?
2193 beq flopin01 | Jump if so
2194
2195 lea dsb1,a1 | Drive B dsb address to a1
2196
2197flopin01: move.w seekrate,2(a1) | Get seek rate
2198 moveq.l #ERR01,d0 | Set default error number
2199 clr.w 0(a1) | Set track number to 0
2200 bsr floplock | Setup floppy parameters
2201 bsr select | Select drive and side
2202 move.w #0xFF00,0(a1)
2203 bsr restore | Restore the drive
2204 moveq.l #6,d7
2205 bsr hseek1
2206 bne flopin02
2207
2208 bsr restore | Restore the drive
2209 beq flopok | Jump if no error
2210
2211flopin02: bra flopfail | Jump to error handler
2212
2213 .page
2214
2215| floprd -- Read floppy
2216| ------ -----------
2217floprd: bsr change | Disk changed ?
2218 moveq.l #ERR11,d0 | Set to "read error"
2219 bsr floplock | Set parameters
2220
2221floprd01: bsr select | Select drive and side
2222 bsr go2track | Position on track
2223 bne floprd02 | Try again on error
2224
2225 move.w #ERR01,deferr | Set default error
2226 move.l edma(a5),a0 | Get final DMA address
2227 move.l cdma(a5),a2 | Get first DMA address
2228 move.l #0x40000,d7 | Set timeout counter
2229 move.b #FL_RM,DSKCMD(a6) | Start readng the disk
2230
2231floprd03: btst #0,DSKCMD(a6) | Disk busy yet ?
2232 bne floprd05 | Jump if so
2233
2234 subq.l #1,d7 | Decrement timeout counter
2235 beq floprd04 | Jump if timed out
2236
2237 bra floprd03 | Go try for busy again
2238
2239floprd05: move.l #0x40000,d7 | Reset timeout counter
2240 bra floprd09 | Go join main read loop
2241
2242floprd07: subq.l #1,d7 | Decrement timeout counter
2243 beq floprd04 | Jump if timed out
2244
2245 btst #0,DSKCMD(a6) | Done yet ?
2246 beq floprd08 | Jump if so
2247
2248floprd09: btst #1,DSKCMD(a6) | DRQ set ?
2249 beq floprd07 | Jump if not
2250
2251 move.b DSKDAT(a6),(a2)+ | Read the byte into the buffer
2252 cmp.l a0,a2 | Done reading ?
2253 bne floprd07 | Jump if not
2254
2255 .page
2256
2257floprd08: move.b DSKCMD(a6),d0 | Read final status into d0
2258 and.b #0x1C,d0 | Mask for error bits
2259 beq flopok | Jump if no errors
2260
2261 bsr errbits | Determine error code
2262
2263floprd02: cmp.w #1,retrycnt(a5) | Re-try ?
2264 bne floprd06 | Jump if not
2265
2266 bsr reseek | Home and repeat the seek
2267
2268floprd06: subq.w #1,retrycnt(a5) | Update re-try count
2269 bpl floprd01 | Re-try if count still >0
2270
2271 bra flopfail | Failure
2272
2273floprd04: move.w #ERR02,curerr(a5) | Set error code "not ready"
2274 bsr rs1772 | Reset the WD1772
2275 bra floprd02 | See if it can be retried
2276
2277 .page
2278
2279| errbits -- Develop error code for floppy I/O error
2280| ------- ---------------------------------------
2281errbits: moveq.l #ERR13,d1 | Write protect ?
2282 btst #6,d0 | ...
2283 bne errbits1 | Jump if so
2284
2285 moveq.l #ERR08,d1 | Record not found ?
2286 btst #4,d0 | ...
2287 bne errbits1 | Jump if so
2288
2289 moveq.l #ERR04,d1 | CRC error ?
2290 btst #3,d0 | ...
2291 bne errbits1 | Jump if so
2292
2293 moveq.l #ERR12,d1 | Lost data ?
2294 btst #2,d0 | ...
2295 bne errbits1 | Jump if so
2296
2297 move.w deferr(a5),d1 | Use default error
2298
2299errbits1: move.w d1,curerr(a5) | ... as curerr
2300 rts | Return to caller
2301
2302 .page
2303
2304| flopwr -- Floppy write
2305| ------ ------------
2306flopwr: bsr change | Check for disk change
2307 moveq.l #ERR10,d0 | Set write error
2308 bsr floplock | Set parameters
2309 move.w csect(a5),d0 | Get sector number in d0
2310 subq.w #1,d0 | ... -1
2311 or.w ctrack(a5),d0 | OR with track number
2312 or.w cside(a5),d0 | OR with side number
2313 bne flopwr01 | Jump if not boot sector
2314
2315 moveq.l #2,d0 | Media change
2316 bsr setdmode | Set to "unsure"
2317
2318flopwr01: bsr select | Select drive and side
2319 bsr go2track | Seek
2320 bne flopwr06 | Re-try on error
2321
2322flopwr02: move.w #ERR01,curerr(a5) | Set for default error
2323 move.l cdma(a5),a2 | Get I/O address
2324 move.l #0x40000,d7 | Set timeout counter
2325 move.w ctrack(a5),d0 | Get track number
2326 cmpi.w #40,d0 | See if we need precomp
2327 bcs flopwr10 | Jump if not
2328
2329 move.b #FL_WS,DSKCMD(a6) | Write with precomp
2330 bra flopwr08 | Go join main write loop
2331
2332flopwr10: move.b #FL_WS+FL_NC,DSKCMD(a6) | Write (no precomp)
2333
2334 .page
2335
2336flopwr08: btst #0,DSKCMD(a6) | Busy yet ?
2337 bne flopwr09 | Jump if so
2338
2339 subq.l #1,d7 | Decrement tiemout count
2340 bne flopwr08 | Jump if not timed out
2341
2342flopwr13: bsr rs1772 | Reset WD1772
2343 bra flopwr05 | See if we can retry
2344
2345flopwr11: btst #0,DSKCMD(a6) | Done ?
2346 beq flopwr04 | Jump if so
2347
2348flopwr09: btst #1,DSKCMD(a6) | DRQ set ?
2349 bne flopwr12 | Jump if so
2350
2351 subq.l #1,d7 | Decrement timeout counter
2352 beq flopwr13 | Jump if timed out
2353
2354 bra flopwr11 | Jump if not
2355
2356flopwr12: move.b (a2)+,DSKDAT(a6) | Write byte to floppy
2357 bra flopwr11 | Go get the next one
2358
2359 .page
2360
2361flopwr04: move.b DSKCMD(a6),d0 | Get floppy status
2362 bsr errbits | Set error code
2363 btst #6,d0 | Write protect error ?
2364 bne flopfail | Fail if so
2365
2366 and.b #0x5C,d0 | Mask error bits
2367 bne flopwr05 | Jump if an error occurred
2368
2369 addq.w #1,csect(a5) | Update sector number
2370 add.l #512,cdma(a5) | Update DMA address
2371 subq.w #1,ccount(a5) | Decrement sector count
2372 beq flopok | Jump if zero -- done
2373
2374 bsr select1 | Set sector and DMA pointer
2375 bra flopwr02 | Write next sector
2376
2377flopwr05: cmp.w #1,retrycnt(a5) | Second re-try ?
2378 bne flopwr07 | Jump if not
2379
2380flopwr06: bsr reseek | Restore and re-seek
2381
2382flopwr07: subq.w #1,retrycnt(a5) | Update re-try count
2383 bpl flopwr01 | Re-try if still >0
2384
2385 bra flopfail | ... else fail
2386
2387 .page
2388
2389| flopfmt -- Format a track on the floppy
2390| ------- ----------------------------
2391flopfmt: cmp.l #FMAGIC,22(a7) | Is the magic right ?
2392 bne flopfail | Fail immediately if not
2393
2394 bsr change | Check for disk change
2395 moveq.l #ERR01,d0 | Set default error number
2396 bsr floplock | Set parameters
2397 bsr select | Select drive and side
2398 move.w 14(a7),spt(a5) | Set sectors per track,
2399 move.w 20(a7),interlv(a5) | ... interleave,
2400 move.w 26(a7),virgin(a5) | ... initial data,
2401 moveq.l #2,d0 | Disk changed
2402 bsr setdmode | ...
2403 bsr hseek | Seek
2404 bne flopfail | Fail if seek error occurs
2405
2406 move.w ctrack(a5),0(a1) | Current track to DSB
2407 move.w #ERR01,curerr(a5) | Default to curerr
2408 bsr fmtrack | Format the track
2409 bne flopfail | Fail if error occurs
2410
2411 move.w spt(a5),ccount(a5) | Use spt as ccount
2412 move.w #1,csect(a5) | Start with sector 1
2413 bsr verify1 | Verify the sector
2414 move.l cdma(a5),a2 | Get bad sector list
2415 tst.w (a2) | Any bad ones ?
2416 beq flopok | Jump if not
2417
2418 move.w #ERR16,curerr(a5) | ERROR -- "bad sectors"
2419 bra flopfail
2420
2421 .page
2422
2423| fmtrack -- Do the dirty work of formatting a track
2424| ------- ---------------------------------------
2425fmtrack: move.w #ERR10,deferr(a5) | Set default error number
2426 move.w #1,d3 | Start with sector 1
2427 move.l cdma(a5),a2 | Get track buffer address
2428 move.w #60-1,d1 | Set count = 60
2429 move.b #0x4E,d0 | Write 0x4E as initial gap
2430 bsr wmult | ...
2431
2432fmtrak01: move.w d3,d4 | Save sector number in d4
2433
2434fmtrak02: move.w #12-1,d1 | Set count = 12
2435 clr.b d0 | Write 0x00 as sync
2436 bsr wmult | ...
2437 move.w #3-1,d1 | Set count = 3
2438 move.b #0xF5,d0 | Write 0xF5's
2439 bsr wmult | ...
2440 move.b #0xFE,(a2)+ | Write 0xFE (address mark)
2441 move.b ctrack+1,(a2)+ | Write track #
2442 move.b cside+1,(a2)+ | Write side #
2443 move.b d4,(a2)+ | Write sector #
2444 move.b #2,(a2)+ | Write sector size code
2445 move.b #0xF7,(a2)+ | Write checksum code
2446 move.w #22-1,d1 | Set count = 22
2447 move.b #0x4E,d0 | Write gap
2448 bsr wmult | ...
2449 move.w #12-1,d1 | Set count = 12
2450 clr.b d0 | Write 0x00 as sync
2451 bsr wmult | ...
2452 move.w #3-1,d1 | Set count = 3
2453 move.b #0xF5,d0 | Write 0xF5's
2454 bsr wmult | ...
2455 move.b #0xFB,(a2)+ | Write DAM
2456 move.w #256-1,d1 | Set count = 256 words
2457
2458 .page
2459
2460fmtrak03: move.b virgin(a5),(a2)+ | Write virgin data in buffer
2461 move.b virgin+1(a5),(a2)+ | ...
2462 dbf d1,fmtrak03 | ...
2463
2464 move.b #0xF7,(a2)+ | Write CRC code
2465 move.w #40-1,d1 | Set count = 40
2466 move.b #0x4E,d0 | Write gap
2467 bsr wmult | ...
2468 add.w interlv(a5),d4 | Add interleave to sector #
2469 cmp.w spt(a5),d4 | Check against spt
2470 ble fmtrak02 | Jump if not >
2471
2472 addq.w #1,d3 | Starting sector +1
2473 cmp.w interlv(a5),d3
2474 ble fmtrak01
2475
2476 move.w #1401-1,d1 | Set count = 1401
2477 move.b #0x4E,d0 | Write final gap
2478 bsr wmult | ...
2479 move.l cdma(a5),a2 | Get buffer address
2480 move.l #0x40000,d7 | Set timeout count
2481 move.w ctrack(a5),d0 | Get track number
2482 cmpi.w #40,d0 | Do we need precomp ?
2483 bcs fmtrak08 | Jump if not
2484
2485 move.b #FL_WT,DSKCMD(a6) | Start format with precomp
2486 bra fmtrak07 | Go join main format loop
2487
2488fmtrak08: move.b #FL_WT+FL_NC,DSKCMD(a6) | Start format without precomp
2489
2490 .page
2491
2492fmtrak07: btst #0,DSKCMD(a6) | Busy yet ?
2493 bne fmtrak09 | Jump if so
2494
2495fmtrak04: subq.l #1,d7 | Decrement timeout counter
2496 bne fmtrak07 | Jump if not timed out
2497
2498fmtrak05: bsr rs1772 | Reset WD1772
2499 moveq.l #1,d7 | Set error flag
2500 rts | Return to caller
2501
2502fmtrak11: btst #0,DSKCMD(a6) | Done ?
2503 beq fmtrak06 | Jump if so
2504
2505fmtrak09: btst #1,DSKCMD(a6) | DRQ set ?
2506 bne fmtrak10 | Jump if so
2507
2508 subq.l #1,d7 | Decrement timeout coutner
2509 beq fmtrak05 | Jump if timed out
2510
2511 bra fmtrak11 | Go check again
2512
2513fmtrak10: move.b (a2)+,DSKDAT(a6) | Write a byte of format
2514 bra fmtrak11 | Go wait for DRQ
2515
2516fmtrak06: move.b DSKCMD(a6),d0 | Get final status
2517 bsr errbits | Set possible error code
2518 andi.b #0x44,d0 | Check error bits
2519 rts | Return to caller with status
2520
2521| wmult -- write multiple bytes into the track buffer
2522| ----- ------------------------------------------
2523wmult: move.b d0,(a2)+ | Move a byte into the buffer
2524 dbf d1,wmult | Loop until we're done
2525
2526 rts | Return to caller
2527
2528 .page
2529
2530| flopver -- verify sector(s) on a floppy
2531| ------- ----------------------------
2532flopver: bsr change | Check for disk change
2533 moveq.l #ERR11,d0 | Set default to "read error"
2534 bsr floplock | Set parameters
2535 bsr select | Select drive and side
2536 bsr go2track | Seek
2537 bne flopfail | Jump if seek error
2538
2539 bsr verify1 | Verify the data
2540 bra flopok | Done
2541
2542| verify1 -- Verify the data for a sector
2543| ------- ----------------------------
2544verify1: move.w #ERR11,deferr(a5) | Set default = "read error"
2545 move.l cdma(a5),a2 | Pointer for bad sector list
2546 add.l #512,cdma(a5) | Update by length of a sector
2547
2548verify01: move.w #2,retrycnt(a5) | Set retrycnt for 2 attempts
2549 move.w csect(a5),d7 | Get sector nubmer
2550 move.b d7,DSKSEC(a6) | Send to WD1772
2551
2552verify02: moveq.l #0,d6 | Clear bad compare flag
2553 move.l cdma(a5),a0 | Get compare address
2554 move.l #0x40000,d7 | Set timeout counter
2555 move.b #FL_RS,DSKCMD(a6) | Start the read
2556
2557verify08: btst #0,DSKCMD(a6) | Busy yet ?
2558 bne verify09 | Jump if so
2559
2560 subq.l #1,d7 | Decrement timeout counter
2561 beq verify13 | Jump if timed out
2562
2563 bra verify08 | Wait for busy some more
2564
2565verify09: move.l #0x40000,d7 | Reset timeout counter
2566 bra verify11 | Go join main compare loop
2567
2568verify10: subq.l #1,d7 | Decrement timeout counter
2569 beq verify13 | Jump if timed out
2570
2571 btst #0,DSKCMD(a6) | Done yet ?
2572 beq verify12 | Jump if so
2573
2574 .page
2575
2576verify11: btst #1,DSKCMD(a6) | DRQ set ?
2577 beq verify10 | Jump if not
2578
2579 move.b DSKDAT(a6),d0 | Read data
2580 bra verify10 | Continue reading
2581
2582verify12: move.b DSKCMD(a6),d0 | Get final status
2583 bsr errbits | Determine error code
2584 and.b #0x1C,d0 | Mask RNF, CRC, LOST
2585 bne verify06 | Jump to re-try if any set
2586
2587verify05: addq.w #1,csect(a5) | Update sector number
2588 subq.w #1,ccount(a5) | Update sector count
2589 bne verify01 | Jump if more to do
2590
2591 sub.l #512,cdma(a5) | Reset DMA pointer
2592 clr.w (a2) | Set NIL in bad sector list
2593 rts | Return to caller
2594
2595verify06: cmp.w #1,retrycnt(a5) | Is it the 2nd attempt ?
2596 bne verify07 | Jump if not
2597
2598 bsr reseek | Restore and re-seek
2599
2600verify07: subq.w #1,retrycnt(a5) | Decrement retry count
2601 bpl verify02 | Re-try if still positive
2602
2603 move.w csect(a5),(a2)+ | Add to bad sector list
2604 bra verify05 | Go do next sector
2605
2606verify13: move.w #ERR02,curerr(a5) | Set timeout error code
2607 bsr rs1772 | Reset WD1772
2608 bra verify06 | See if we can retry it
2609
2610 .page
2611
2612| flopvbl -- Floppy VBL timer interrupt handling
2613| ------- -----------------------------------
2614flopvbl: movem.l d0-d1/a0-a1/a5-a6,-(a7) | Save registers
2615 sub.l a5,a5 | Clear a5 for use as RAM base
2616 lea FLOPPY,a6 | Base of floppy regs
2617 st motoron(a5) | Set motoron flag
2618 move.l frclock(a5),d0 | Get interrupt count
2619 move.b d0,d1 | ...
2620 and.b #7,d1 | ... MOD 8
2621 bne flopvb02 | Jump if not 8th int
2622
2623 move.w sr,-(a7) | Save interrupt level
2624 ori.w #IPL7,sr | Mask off interrupts
2625 clr.w deslflag(a5) | Clear deselect flag
2626 move.b mc1iorec+cfr1,d0 | Get port status
2627 ori.b #1,d0 | Set drive select bit
2628 move.b d0,MC1ACIA+ACIA_CFR | Send drive select to port
2629 move.b d0,mc1iorec+cfr1 | Store updated port status
2630 move.w (a7)+,sr | Restore interrupt level
2631 lea wpstatus(a5),a0 | Point at wpstatus for drive
2632 lea dsb0(a5),a1 | Point at dsb0
2633 move.b DSKCMD(a6),d0 | Read WD1772 status
2634 btst #6,d0 | Test write protect bit
2635 sne (a0) | ... and save
2636
2637 .page
2638
2639flopvb02: move.w wpstatus(a5),d0 | Get wpstatus of drive A
2640 or.w d0,wplatch(a5) | OR into wplatch
2641 tst.w deslflag(a5) | Floppies already deselected ?
2642 bne flopvb03 | Jump if so
2643
2644 move.b DSKCMD(a6),d0 | Read WD1772 status
2645 btst #7,d0 | Motor-on bit set ?
2646 bne flopvb04 | Don't de-select if it is
2647
2648 move.w sr,-(a7) | Save sr
2649 ori.w #IPL7,sr | Disable interrupts
2650 move.b mc1iorec+cfr1,d0 | Get cfr1 image
2651 bclr #0,d0 | Clear d0 (drive select)
2652 move.b d0,mc1iorec+cfr1 | Save new value
2653 move.b d0,MC1ACIA+ACIA_CFR | Send to hardware
2654 move.w (a7)+,sr | Restore sr (enable ints)
2655 move.w #1,deslflag(a5) | Set the deselect flag
2656
2657flopvb03: clr.w motoron(a5) | Clear motoron flag
2658
2659flopvb04: movem.l (a7)+,d0-d1/a0-a1/a5-a6 | Restore registers
2660 rts | Return to caller
2661
2662 .page
2663
2664| floplock -- Setup floppy parameters
2665| -------- -----------------------
2666floplock: movem.l d3-d7/a3-a6,flpregs | Save registers
2667 move.w sr,flpsrsv | Save sr
2668 ori.w #IPL7,sr | Disable ints
2669 sub.l a5,a5 | Clear a5
2670 lea FLOPPY,a6 | Base of floppy registers
2671 st motoron(a5) | Set motoron flag
2672 move.w d0,deferr(a5) | Set default error code
2673 move.w d0,curerr(a5) | ... current error code
2674 move.w #1,flock(a5) | Disable flopvbl routine
2675 move.l 8(a7),cdma(a5) | Set cdma
2676 move.w 16(a7),cdev(a5) | ... cdev
2677 move.w 18(a7),csect(a5) | ... csect
2678 move.w 20(a7),ctrack(a5) | ... ctrack
2679 move.w 22(a7),cside(a5) | ... cside
2680 move.w 24(a7),ccount(a5) | ... ccount
2681 move.w #2,retrycnt(a5) | ... retrycnt
2682 lea dsb0(a5),a1 | Address of dsb0
2683 tst.w cdev(a5) | Drive A ?
2684 beq floplk01 | Jump if so
2685
2686 lea dsb1(a5),a1 | Drive B, use dsb1
2687
2688floplk01: moveq.l #0,d7 | Clear out d7
2689 move.w ccount(a5),d7 | Get ccount
2690 lsl.w #8,d7 | ... * sector length (512)
2691 lsl.w #1,d7 | ...
2692 move.l cdma(a5),a0 | Get DMA start address
2693 add.l d7,a0 | Add length of sectors
2694 move.l a0,edma(a5) | Set edma (end DMA address)
2695 tst.w 0(a1) | Check current track
2696 bpl floplk03 | Jump if >= 0
2697
2698 bsr select | Select the drive
2699 clr.w 0(a1) | Set current track to 0
2700 bsr restore | Restore drive to track 0
2701 beq floplk03 | Jump if OK
2702
2703 moveq.l #10,d7 | Seek out to track 10
2704 bsr hseek1 | ...
2705 bne floplk02 | Jump if an error occurred
2706
2707 bsr restore | Try the restore again
2708 beq floplk03 | Jump if OK
2709
2710floplk02: move.w #0xFF00,0(a1) | Recalibrate error
2711
2712floplk03: rts | Return to caller
2713
2714 .page
2715
2716| flopfail -- Floppy I/O failure exit
2717| -------- -----------------------
2718flopfail: moveq.l #1,d0 | Set media change to "unsure"
2719 bsr setdmode | ...
2720 move.w curerr(a5),d0 | Get curerr
2721 ext.l d0 | ...
2722 bra flopok1 | Go set end status
2723
2724| flopok -- Floppy I/O success exit
2725| ------ -----------------------
2726flopok: clr.l d0 | Set error code = 0 (no error)
2727
2728flopok1: move.l d0,-(a7) | Push code onto stack
2729 move.w 0(a1),d7 | Get track number
2730 move.b d7,DSKDAT(a6) | Send to WD1772
2731 move.w #FL_SK,d6 | Seek command to d6
2732 bsr flopcmds | Send command
2733 move.w cdev(a5),d0 | Get drive number
2734 lsl.w #2,d0 | Use as index
2735 lea acctim(a5),a0 | ... into acctim
2736 move.l hz_200(a5),0(a0,d0) | Set last access time
2737 cmp.w #1,nflops(a5)
2738 bne flopok01
2739
2740 move.l hz_200(a5),4(a0) | Time for other drive
2741
2742flopok01: move.w flpsrsv,sr | Restore sr (enable ints)
2743 move.l (a7)+,d0 | Restore error number to d0
2744 movem.l flpregs,d3-d7/a3-a6 | Restore registers
2745 clr.w flock | Release flopvbl routine
2746 rts | Return to caller
2747
2748 .page
2749
2750| hseek -- seek to track in ctrack
2751| ----- -----------------------
2752hseek: move.w ctrack,d7 | Get ctrack
2753
2754| hseek1 -- seek to track in d7
2755| ------ -------------------
2756hseek1: move.w #ERR10,curerr | Set curerr = "seek error"
2757 move.b d7,DSKDAT(a6) | Send track number to WD1772
2758 move.w #FL_SK,d6 | Seek command
2759 bra flopcmds | Go send command to WD1772
2760
2761| reseek -- Restore, then re-seek
2762| ------ ---------------------
2763reseek: move.w #ERR10,curerr | Set curerr = "seek error"
2764 bsr restore | Restore
2765 bne reseek01 | Jump if error occurred
2766
2767 clr.w 0(a1) | Clear current track to 0
2768 move.b #0,DSKTRK(a6) | Send track to WD1772
2769 move.b #5,DSKDAT(a6) | Setup to seek to track 5
2770 move.w #FL_SK,d6 | Seek command
2771 bsr flopcmds | Seek
2772 bne reseek01 | Jump if error
2773
2774 move.w #5,0(a1) | Update current track = 5
2775
2776| go2track -- seek with verify
2777| -------- ----------------
2778go2track: move.w #ERR10,curerr(a5) | Set curerr = "seek error"
2779 move.w ctrack(a5),d7 | Put track # in d7
2780 move.b d7,DSKDAT(a6) | Send track to WD1772
2781 moveq.l #FL_SV,d6 | Seek/verify command
2782 bsr flopcmds | Send command to floppy
2783 bne reseek01 | Jump if error occurred
2784
2785 move.w ctrack(a5),0(a1) | Update track number in dsb
2786 and.b #0x18,d7 | Test for RNF, CRC, LOST
2787
2788reseek01: rts | Return to caller
2789
2790 .page
2791
2792| restore -- Restore to track 0
2793| ------- ------------------
2794restore: clr.w d6 | Restore command
2795 bsr flopcmds | Send to WD1772
2796 bne restor01 | Jump if an error occurred
2797
2798 btst #2,d7 | Check track 0 bit
2799 eori #0004,sr | Invert Z flag in 680000 sr
2800 bne restor01 | Jump if not track 0
2801
2802 clr.w 0(a1) | Set track = 0 in dsb
2803
2804restor01: rts | Return to caller
2805
2806| flopcmds -- Send command to WD1772 floppy controller
2807| -------- ----------------------------------------
2808flopcmds: move.w 2(a1),d0 | Get seek rate from dsb
2809 and.b #0x3,d0 | ...
2810 or.b d0,d6 | OR into command word
2811 move.l #0x40000,d7 | Set timeout counter
2812 btst #7,DSKCMD(a6) | Motor on ?
2813 bne flopcm01 | Jump if so
2814
2815 move.l #0x60000,d7 | Set longer timeout count
2816
2817flopcm01: move.b d6,DSKCMD(a6) | Write command from d6
2818
2819 move.l #0x1000,d0 | Set initial busy timeout in d0
2820
2821flopcm04: btst #0,DSKCMD(a6) | Controller busy yet ?
2822 bne flopcm02 | Jump if so
2823
2824 subq.l #1,d0 | Decrement timeout counter
2825 beq flopcm03 | Jump if timed out
2826
2827 bra flopcm04 | Wait for busy some more
2828
2829flopcm02: subq.l #1,d7 | Decrement timeout counter
2830 beq flopcm03 | Jump if timed out
2831
2832 btst #0,DSKCMD(a6) | WD1772 done ?
2833 bne flopcm02 | Jump if not
2834
2835 clr.l d7 | Clear out upper bits of d7
2836 move.b DSKCMD(a6),d7 | Read status into LS byte of d7
2837 clr.l d6 | Clear error flag in d6
2838 rts | Return to caller
2839
2840flopcm03: bsr rs1772 | Reset WD1772 (end transfer)
2841 moveq.l #1,d6 | Set error flag in d6
2842 rts | Return to caller
2843
2844 .page
2845
2846| rs1772 -- Reset WD1772 floppy controller
2847| ------ ------------------------------
2848rs1772: move.b #FL_FR,DSKCMD(a6) | Send reset to WD1772
2849 move.w #15,d7 | Set delay count
2850
2851rs1772a: dbf d7,rs1772a | Delay a while
2852 rts | Return to caller
2853
2854| select -- Select drive and side
2855| ------ ----------------------
2856select: move.w sr,-(a7) | Save sr on stack
2857 ori.w #IPL7,sr | Disable interrupts
2858 clr.w deslflag(a5) | Clear deselect flag
2859 move.b mc1iorec+cfr1,d0 | Get current MC1 cfr1 image
2860 ori.b #1,d0 | Select drive (we only have 1)
2861 move.b d0,mc1iorec+cfr1 | Store updated image
2862 move.b d0,MC1ACIA+ACIA_CFR | Send it to the MC1 ACIA
2863 move.w cside(a5),d0 | Get side number (LS bit)
2864 and.w #1,d0 | Mask off garbage bits
2865 andi.b #0xFE,mc2iorec+cfr1 | Mask off D0 in MC2 cfr1 image
2866 or.b mc2iorec+cfr1,d0 | OR side with mc2iorec cfr1
2867 move.b d0,mc2iorec+cfr1 | Store updated cfr1 image
2868 move.b d0,MC2ACIA+ACIA_CFR | Send it to the MC2 ACIA
2869 move.w (a7)+,sr | Restore interrupts
2870 move.w 0(a1),d7 | Get track from dsb
2871 move.b d7,DSKTRK(a6) | Send it to the WD1772
2872 clr.b tmpdma(a5) | Clear bits 31..24 of tmpdma
2873
2874select1: move.w csect(a5),d7 | Get sector number
2875 move.b d7,DSKSEC(a6) | Send it to the WD1772
2876 move.l cdma(a5),a0 | Setup transfer address in a0
2877 rts | Return to caller
2878
2879 .page
2880
2881| change -- Check for disk change status
2882| ------ ----------------------------
2883change: cmp.w #1,nflops | Check # of floppies
2884 bne change02
2885
2886 move.w 16(a7),d0 | Drive number to d0
2887 cmp.w disknum,d0
2888 beq change01 | Jump if =
2889
2890 move.w d0,-(a7) | Stack drive number
2891 move.w #ERR17,-(a7) | Stack error code
2892 bsr criter | Do critical error routine
2893 addq.w #4,a7 | Cleanup stack
2894 move.w #0xFFFF,wplatch | Status for drives = "unsure"
2895 move.w 16(a7),disknum | Save disk number
2896
2897change01: clr.w 16(a7) | Clear disk number
2898
2899change02: rts | Return to caller
2900
2901| setdmode -- Set drive change mode
2902| -------- ---------------------
2903setdmode: lea dskmode,a0 | Point at disk mode table
2904 move.b d0,-(a7) | Save mode on stack
2905 move.w cdev(a5),d0 | Get drive number
2906 move.b (a7)+,0(a0,d0) | Set drive mode / cleanup stack
2907 rts | Return to caller
2908
2909 .page
2910
2911| bootload -- Load boot sector
2912| -------- ----------------
2913bootload: link a6,#0 | Link stack frames
2914 movem.l d6-d7,-(a7) | Save registers
2915 jsr hdvini | Init drive
2916 tst.w nflops | See if any connected
2917 beq bootld01 | Jump if drive there
2918
2919 moveq.l #1,d0 | "couldn't load"
2920 bra bootld02
2921
2922bootld01: moveq.l #2,d0 | "no drive connected"
2923
2924bootld02: move.w d0,d7 | Save possible error in d7
2925 tst.w nflops
2926 beq bootld04
2927
2928 cmp.w #2,bootdev
2929 bge bootld04
2930
2931 move.w #1,(a7) | Sector count = 1,
2932 clr.w -(a7) | ... side = 0,
2933 clr.w -(a7) | ... track = 0,
2934 move.w #1,-(a7) | ... sector = 1,
2935 move.w bootdev,-(a7) | ... drive = bootdev,
2936 clr.l -(a7) | ... filler,
2937 move.l #buffer,-(a7) | ... buffer address
2938 jsr floprd | Read the sector
2939 add.l #16,a7 | Cleanup stack
2940 tst.l d0 | Error ?
2941 bne bootld03 | Jump if not
2942
2943 clr.w d7
2944 bra bootld04
2945
2946bootld03: tst.b wpstatus
2947 bne bootld04
2948
2949 moveq.l #3,d0 | "unreadable"
2950 bra bootld07
2951
2952bootld04: tst.w d7
2953 beq bootld05
2954
2955 move.w d7,d0 | Get old error code
2956 bra bootld07
2957
2958 .page
2959
2960bootld05: move.w #256,(a7) | Set count for 256 words
2961 move.l #buffer,-(a7) | Point at buffer
2962 bsr chksum | Calculate checksum
2963 addq.l #4,a7 | Cleanup stack
2964 cmp.w #0x1234,d0 | Boot sector checksum ?
2965 bne bootld06 | Jump if not
2966
2967 clr.w d0 | Set flag for OK
2968 move.w bootdev,booted | Save last boot device
2969 bra bootld07
2970
2971bootld06: moveq.l #4,d0 | "not valid boot sector"
2972
2973bootld07: tst.l (a7)+
2974 movem.l (a7)+,d7 | Restore registers
2975 unlk a6
2976 rts | Return to caller
2977
2978 .page
2979
2980| chksum -- caluculate checksum
2981| ------ -------------------
2982chksum: link a6,#0
2983 movem.l d6-d7,-(a7) | Preserve registers
2984 clr.w d7 | Clear sum
2985 bra chksum02 | Jump into loop
2986
2987chksum01: move.l 8(a6),a0 | Get buffer address
2988 move.w (a0),d0 | Get word
2989 add.w d0,d7 | Add to checksum in d7
2990 addq.l #2,8(a6) | Update buffer address
2991
2992chksum02: move.w 12(a6),d0 | Get word count
2993 subq.w #1,12(a6) | Decrement it
2994 tst.w d0 | Done ?
2995 bne chksum01 | Loop if not
2996
2997 move.w d7,d0 | Put result in d0
2998 tst.l (a7)+
2999 movem.l (a7)+,d7 | Restore registers
3000 unlk a6
3001 rts | Return to caller
3002
3003 .page
3004
3005| mult32 -- 32 bit signed multiply
3006| ------ ----------------------
3007mult32: link a6,#-4
3008 clr.w d2
3009 tst.l 8(a6)
3010 bge mult32a
3011
3012 neg.l 8(a6)
3013 addq.w #1,d2
3014
3015mult32a: tst.l 12(a6)
3016 bge mult32b
3017
3018 neg.l 12(a6)
3019 addq.w #1,d2
3020
3021mult32b: move.w 10(a6),d0
3022 mulu 14(a6),d0
3023 move.l d0,-4(a6)
3024 move.w 8(a6),d0
3025 mulu 14(a6),d0
3026 move.w 12(a6),d1
3027 mulu 10(a6),d1
3028 add.w d1,d0
3029 add.w -4(a6),d0
3030 move.w d0,-4(a6)
3031 move.l -4(a6),d0
3032 btst #0,d2
3033 beq mult32c
3034
3035 neg.l d0
3036
3037mult32c: unlk a6
3038 rts
3039
3040 .page
3041
3042| rand -- Generate a random number
3043| ---- ------------------------
3044rand: link a6,#-4 | Reserve stack for temps
3045 tst.l rseed | See if the seed is zero
3046 bne rand01 | Jump if not
3047
3048 move.l hz_200,d0 | Pick up the 200 Hz clock
3049 moveq.l #16,d1 | Shift it left
3050 asl.l d1,d0 | ...
3051 or.l hz_200,d0 | OR in current 200 Hz clock
3052 move.l d0,rseed | Use that as the seed
3053
3054rand01: move.l #0xBB40E62D,-(a7) | Put PI on the stack
3055 move.l rseed,-(a7) | ... and rseed, too
3056 bsr mult32 | Multiply them
3057 addq.l #8,a7 | Cleanup stack
3058 addq.l #1,d0 | Add 1 to the result
3059 move.l d0,rseed | Save as new seed
3060 move.l rseed,d0
3061 asr.l #8,d0 | Make it a 24 bit number
3062 and.l #0xFFFFFF,d0 | ...
3063 unlk a6 | Release stack
3064 rts | Return to caller
3065
3066 .page
3067
3068| protobt -- Generate a prototype boot sector
3069| ------- --------------------------------
3070protobt: link a6,#-6
3071 movem.l d5-d7/a5,-(a7) | Save registers
3072 tst.w 18(a6) | Test execflg
3073 bge protbt03 | Jump if set
3074
3075 move.w #256,(a7) | Count = 256 words
3076 move.l 8(a6),-(a7) | Address of buffer
3077 bsr chksum | Calculate checksum
3078 addq.l #4,a7 | Cleanup stack
3079 cmp.w #0x1234,d0 | Boot checksum ?
3080 beq protbt01 | Jump if so
3081
3082 clr.w d0 | Not executable
3083 bra protbt02
3084
3085protbt01: moveq.l #1,d0 | Executable
3086
3087protbt02: move.w d0,18(a6) | Set execflg
3088
3089protbt03: tst.l 12(a6) | Serial number ?
3090 blt protbt07 | Jump if not to be changed
3091
3092 move.l 12(a6),d0 | Get it into d0
3093 cmp.l #0xFFFFFF,d0 | > 0xFFFFFF
3094 ble protbt04 | Jump if not
3095
3096 bsr rand | Generate a random number
3097 move.l d0,12(a6) | Save as s/n
3098
3099protbt04: clr.w d7 | Clear counter
3100 bra protbt06 | Enter move loop
3101
3102 .page
3103
3104protbt05: move.l 12(a6),d0 | Get s/n
3105 and.l #0xFF,d0 | Isolate low 8 bits
3106 move.w d7,a1 | Point to next byte
3107 add.l 8(a6),a1 | ...
3108 move.b d0,8(a1) | Write byte in buffer
3109 move.l 12(a6),d0 | Get s/n
3110 asr.l #8,d0 | Shift right 8 bits
3111 move.l d0,12(a6) | Save shifted value
3112 addq.w #1,d7 | Update counter
3113
3114protbt06: cmp.w #3,d7 | See if we're done
3115 blt protbt05 | Loop if not
3116
3117protbt07: tst.w 16(a6) | Diskette size ?
3118 blt protbt10 | Jump if not to be changed
3119
3120 move.w 16(a6),d6 | Get diskette size
3121 muls.w #19,d6 | ... times 19 as pointer
3122 clr.w d7 | Clear counter
3123 bra protbt09 | Go move in BPB
3124
3125protbt08: move.w d7,a0 | Get counter
3126 add.l 8(a6),a0 | Add base of buffer
3127 move.w d6,a1 | Get BPB pointer
3128 add.l #pbpbtab,a1 | Add base of prototype BPB's
3129 move.b (a1),11(a0) | Copy BPB data
3130 addq.w #1,d6 | Update pointer
3131 addq.w #1,d7 | Update counter
3132
3133protbt09: cmp.w #19,d7 | Done ?
3134 blt protbt08 | Loop if not
3135
3136protbt10: clr.w -6(a6)
3137 move.l 8(a6),-4(a6)
3138 bra protbt12
3139
3140 .page
3141
3142protbt11: move.l -4(a6),a0 | Get buffer pointer
3143 move.w (a0),d0 | Get word from buffer
3144 add.w d0,-6(a6) | Sum for checksum
3145 addq.l #2,-4(a6) | Point at next word
3146
3147protbt12: move.l 8(a6),d0 | Get buffer address
3148 add.l #0x1FE,d0 | Plus sector length
3149 cmp.l -4(a6),d0 | Done ?
3150 bhi protbt11 | Loop if not
3151
3152 move.w #0x1234,d0 | Checksum for boot sector
3153 sub.w -6(a6),d0 | Subtract checksum for buffer
3154 move.l -4(a6),a1
3155 move.w d0,(a1) | Store checksum in buffer
3156 tst.w 18(a6) | Check execflg
3157 bne protbt13 | Boot sector to be executable ?
3158
3159 move.l -4(a6),a0 | Mung checksum so it's not
3160 addq.w #1,(a0)
3161
3162protbt13: tst.l (a7)+
3163 movem.l (a7)+,d6-d7/a5 | Restore registers
3164 unlk a6 | Release stack
3165 rts | Return to caller
3166
3167 .endc
3168
3169| criter -- Critical error handler
3170| ------ ----------------------
3171criter: move.l critvec,-(a7) | Put error vector on stack
3172 moveq.l #-1,d0 | Set default error return
3173 rts | "Return" to handler
3174
3175 .page
3176
3177 .ifne BUCHLA
3178
3179| api_int -- Analog processor interrupt handler
3180| ------- ----------------------------------
3181api_int: movem.l d0-d1/a0-a1,-(a7) | Save registers
3182 clr.l d0 | Read input port
3183 move.b ANALOG,d0 | ... into d0[7..0]
3184 move.b d0,api_inp | ... and api_inp
3185 btst #7,d0 | Check for signal number flag
3186 bne api_s0a | Jump if signal number read
3187
3188 lea api_tv,a0 | Get api_tv base in a0
3189 clr.w d1 | Get api_sv in d1
3190 move.b api_sv,d1 | ...
3191 cmpi.b #6,d1 | Check range
3192 bgt api_sve | Jump if out of range
3193
3194 lsl.w #2,d1 | Develop jump address
3195 move.l 0(a0,d1.W),a1 | ... from api_tv in a1
3196 jmp (a1) | Jump to state handler
3197
3198api_s0: btst #7,d0 | Check for signal number flag
3199 beq api_ret | Jump if not signal number
3200
3201api_s0a: clr.b api_val | Clear value byte
3202 andi.b #0x7F,d0 | Mask off signal number flag
3203 cmpi.b #82,d0 | See if it's in range
3204 bgt api_err | Jump if out of range (GT 82)
3205
3206 move.b d0,api_sig | Store signal number
3207 beq api_pub | Jump if it was "all off"
3208
3209 lea api_tab,a0 | Get sv table base
3210 move.b 0(a0,d0.W),api_sv | Set sv for next time
3211
3212api_ret: movem.l (a7)+,d0-d1/a0-a1 | Restore registers
3213 rte | Return to interrupted code
3214
3215api_err: move.b d0,api_bug | Catch the bug
3216 clr.b api_sv | Force state zero
3217 bra api_ret | Go back to interrupted code
3218
3219api_sve: move.b d1,api_svb | Catch the bug
3220 clr.b api_sv | Force state zero
3221 bra api_ret | Go back to interrupted code
3222
3223 .page
3224api_s1: btst #0,d0 | See if it takes a value
3225 beq api_s1a | Jump if not
3226
3227 move.b #2,api_sv | Set sv for state 2
3228 bra api_ret | Go return from interrupt
3229
3230api_s1a: clr.b api_val | Clear value byte
3231 bra api_pub | Go output to fifo
3232
3233api_s2: ori.b #0x80,d0 | Set status = 1
3234 move.b d0,api_val | Set value byte
3235 bra api_pub | Go output to fifo
3236
3237api_s3: ror.b #1,d0 | Set status in value byte
3238 andi.b #0x80,d0 | ...
3239 move.b d0,api_val | ...
3240 move.b #4,api_sv | Set sv for state 4
3241 bra api_ret | Go return from interrupt
3242
3243api_s4: or.b d0,api_val | Set value byte
3244 bra api_pub | Go output to fifo
3245
3246api_s5: ror.b #1,d0 | Set status in value byte
3247 andi.b #0x80,d0 | ...
3248
3249api_s6: move.b d0,api_val | Set value byte
3250
3251api_pub: movea.l api_fi,a0 | Get fifo input pointer in a0
3252 move.w api_sig,(a0)+ | Store new input
3253 cmpa.l #api_fe,a0 | Wrap around ?
3254 blt api_pb1 | Jump if not
3255
3256 movea.l #api_fum,a0 | Wrap input pointer to start
3257
3258api_pb1: move.l a0,api_fi | Update input pointer
3259 cmpa.l api_fo,a0 | Buffer full ?
3260 bne api_pb3 | Jump if not
3261
3262 movea.l api_fo,a1 | Get fifo output pointer in a1
3263 adda.l #2,a1 | Increment it
3264 cmpa.l #api_fe,a1 | Wrap around ?
3265 blt api_pb2 | Jump if not
3266
3267 movea.l #api_fum,a1 | Wrap output pointer to start
3268
3269api_pb2: move.l a1,api_fo | Set new output pointer
3270
3271api_pb3: clr.b api_sv | Set state to 0
3272 bra api_ret | Return from interrupt
3273
3274 .page
3275
3276| api_get -- Get analog input
3277| ------- ----------------
3278api_get: move.w sr,-(a7) | Save status register
3279 ori.w #IPL3,sr | Disable ANALOG I/O interrupts
3280 movea.l api_fo,a0 | Get fifo output pointer
3281 cmpa.l api_fi,a0 | See if fifo is empty
3282 bne api_g1 | Jump if not
3283
3284 moveq.l #-1,d0 | Set empty-fifo value
3285 move.w (a7)+,sr | Restore interrupt mask
3286 rts | Return to caller
3287
3288api_g1: clr.l d0 | Get fifo value
3289 move.w (a0)+,d0 | ...
3290 cmpa.l #api_fe,a0 | See if pointer wrapped
3291 blt api_g2 | Jump if not
3292
3293 movea.l #api_fum,a0 | Wrap the pointer around
3294
3295api_g2: move.l a0,api_fo | Update pointer
3296 move.w (a7)+,sr | Restore interrupt mask
3297 rts | Return to caller
3298
3299| api_zap -- clear analog I/O FIFO
3300| ------- ---------------------
3301api_zap: move.w sr,-(a7) | Save status register
3302 ori.w #IPL3,sr | Disable ANALOG I/O interrupts
3303 move.l #api_fum,api_fi | Clear analog processor fifo
3304 move.l #api_fum,api_fo | ...
3305 move.w (a7)+,sr | Restore interrupt mask
3306 rts
3307
3308 .endc
3309
3310 .page
3311|************************************************************************
3312| |
3313| Constant definitions |
3314| -------------------- |
3315|************************************************************************
3316
3317 .even
3318
3319 .ifne BUCHLA
3320
3321| Buchla 700 tables:
3322
3323| t13tab -- Trap-13 pointer table -- Primary BIOS functions
3324| ------ -----------------------------------------------
3325t13tab: .dc.w 12 | Number of Trap-13 routines
3326
3327 .dc.l nullrts | 0 - (getmpb)
3328 .dc.l bconstat | 1 - bconstat
3329 .dc.l bconin | 2 - bconin
3330 .dc.l bconout | 3 - bconout
3331 .dc.l rwabs | 4 - rwabs
3332 .dc.l setexec | 5 - setexec
3333 .dc.l nullrts | 6 - (tickcal)
3334 .dc.l getbpb | 7 - getbpb
3335 .dc.l bcostat | 8 - bcostat
3336 .dc.l mediach | 9 - mediach
3337 .dc.l drvmap | 10 - drvmap
3338 .dc.l nullrts | 11 - (shift)
3339
3340 .page
3341
3342| t14tab -- Trap-14 pointer table -- Extended BIOS functions (Buchla 700 only)
3343| ------ ------------------------------------------------------------------
3344t14tab: .dc.w 10 | Number of trap14 routines
3345
3346 .dc.l piorec | 0 - Get iorec address
3347 .dc.l setport | 1 - Set ACIA parameters
3348 .dc.l floprd | 2 - Read floppy
3349 .dc.l flopwr | 3 - Write floppy
3350 .dc.l flopfmt | 4 - Format floppy
3351 .dc.l flopver | 5 - Verify floppy
3352 .dc.l protobt | 6 - Create prototype boot sec.
3353 .dc.l rand | 7 - Generate random number
3354 .dc.l api_get | 8 - Get analog input
3355 .dc.l api_zap | 9 - Clear analog FIFO
3356
3357 .endc
3358
3359 .even
3360
3361 .ifeq BUCHLA
3362
3363| NASA 3D Helmet tables:
3364
3365| t13tab -- Trap-13 pointer table -- Primary BIOS functions
3366| ------ -----------------------------------------------
3367t13tab: .dc.w 12 | Number of Trap-13 routines
3368
3369 .dc.l nullrts | 0 - (getmpb)
3370 .dc.l bconstat | 1 - bconstat
3371 .dc.l bconin | 2 - bconin
3372 .dc.l bconout | 3 - bconout
3373 .dc.l nullrts | 4 - (rwabs)
3374 .dc.l setexec | 5 - setexec
3375 .dc.l nullrts | 6 - (tickcal)
3376 .dc.l nullrts | 7 - (getbpb)
3377 .dc.l bcostat | 8 - bcostat
3378 .dc.l nullrts | 9 - (mediach)
3379 .dc.l nullrts | 10 - (drvmap)
3380 .dc.l nullrts | 11 - (shift)
3381
3382 .page
3383
3384| t14tab -- Trap-14 pointer table -- Extended BIOS functions (Buchla 700 only)
3385| ------ ------------------------------------------------------------------
3386t14tab: .dc.w 10 | Number of trap14 routines
3387
3388 .dc.l piorec | 0 - Get iorec address
3389 .dc.l setport | 1 - Set ACIA parameters
3390 .dc.l nullrts | 2 - (Read floppy)
3391 .dc.l nullrts | 3 - (Write floppy)
3392 .dc.l nullrts | 4 - (Format floppy)
3393 .dc.l nullrts | 5 - (Verify floppy)
3394 .dc.l nullrts | 6 - (Create prototype boot sec.)
3395 .dc.l nullrts | 7 - (Generate random number)
3396 .dc.l nullrts | 8 - (Get analog input)
3397 .dc.l nullrts | 9 - (Clear analog FIFO)
3398
3399 .endc
3400
3401 .page
3402
3403| cdt01 -- Character device dispatch table #1 -- input status
3404| ----- --------------------------------------------------
3405cdt01: .dc.l sr1ist | 0 - PRT -- Printer
3406 .dc.l sr2ist | 1 - AUX -- Serial-2
3407 .dc.l sr2ist | 2 - CON -- Console
3408
3409 .ifne BUCHLA
3410
3411 .dc.l mc1ist | 3 - MC1 -- MIDI-1
3412 .dc.l mc2ist | 4 - MC2 -- MIDI-2
3413
3414 .endc
3415
3416| cdt02 -- Character device dispatch table #2 -- input
3417| ----- -------------------------------------------
3418cdt02: .dc.l sr1inp | 0 - PRT -- Printer
3419 .dc.l sr2inp | 1 - AUX -- Serial-2
3420 .dc.l sr2inp | 2 - CON -- Console
3421
3422 .ifne BUCHLA
3423
3424 .dc.l mc1inp | 3 - MC1 -- MIDI-1
3425 .dc.l mc2inp | 4 - MC2 -- MIDI-2
3426
3427 .endc
3428
3429| cdt03 -- Character device dispatch table #3 -- output
3430| ----- --------------------------------------------
3431cdt03: .dc.l sr1out | 0 - PRT -- Printer
3432 .dc.l sr2out | 1 - AUX -- Serial-2
3433 .dc.l sr2out | 2 - CON -- Console
3434 .ifne BUCHLA
3435
3436 .dc.l mc1out | 3 - MC1 -- MIDI-1
3437 .dc.l mc2out | 4 - MC2 -- MIDI-2
3438
3439 .endc
3440
3441| cdt04 -- Character device dispatch table #4 -- output status
3442| ----- ---------------------------------------------------
3443cdt04: .dc.l sr1ost | 0 - PRT -- Printer
3444 .dc.l sr2ost | 1 - AUX -- Serial-2
3445 .dc.l sr2ost | 2 - CON -- Console
3446 .ifne BUCHLA
3447
3448 .dc.l mc1ost | 3 - MC1 -- MIDI-1
3449 .dc.l mc2ost | 4 - MC2 -- MIDI-2
3450
3451 .endc
3452
3453 .page
3454
3455| iorec defaults:
3456| ---------------
3457| Serial-1:
3458| ---------
3459sr1dflt: .dc.l sr1ibuf
3460 .dc.w SR1IBS
3461 .dc.w 0,0
3462 .dc.w SR1IBS/4
3463 .dc.w SR1IBS-(SR1IBS/4)
3464 .dc.l sr1obuf
3465 .dc.w SR1OBS
3466 .dc.w 0,0
3467 .dc.w SR1OBS/4
3468 .dc.w SR1OBS-(SR1OBS/4)
3469 .dc.b SR1CFR0,SR1CFR1
3470 .dc.b 0,0
3471 .dc.b SR1DISC,0
3472 .dc.b 0,0
3473 .dc.w 0,0
3474
3475| Serial-2:
3476| ---------
3477sr2dflt: .dc.l sr2ibuf
3478 .dc.w SR2IBS
3479 .dc.w 0,0
3480 .dc.w SR2IBS/4
3481 .dc.w SR2IBS-(SR2IBS/4)
3482 .dc.l sr2obuf
3483 .dc.w SR2OBS
3484 .dc.w 0,0
3485 .dc.w SR2OBS/4
3486 .dc.w SR2OBS-(SR2OBS/4)
3487 .dc.b SR2CFR0,SR2CFR1
3488 .dc.b 0,0
3489 .dc.b SR2DISC,0
3490 .dc.b 0,0
3491 .dc.w 0,0
3492
3493 .page
3494
3495 .ifne BUCHLA
3496
3497| MIDI-1:
3498| -------
3499mc1dflt: .dc.l mc1ibuf
3500 .dc.w MC1IBS
3501 .dc.w 0,0
3502 .dc.w MC1IBS/4
3503 .dc.w MC1IBS-(MC1IBS/4)
3504 .dc.l mc1obuf
3505 .dc.w MC1OBS
3506 .dc.w 0,0
3507 .dc.w MC1OBS/4
3508 .dc.w MC1OBS-(MC1OBS/4)
3509 .dc.b MC1CFR0,MC1CFR1
3510 .dc.b 0,0
3511 .dc.b MC1DISC,0
3512 .dc.b 0,0
3513 .dc.w 0,0
3514
3515| MIDI-2:
3516| -------
3517mc2dflt: .dc.l mc2ibuf
3518 .dc.w MC2IBS
3519 .dc.w 0,0
3520 .dc.w MC2IBS/4
3521 .dc.w MC2IBS-(MC2IBS/4)
3522 .dc.l mc2obuf
3523 .dc.w MC2OBS
3524 .dc.w 0,0
3525 .dc.w MC2OBS/4
3526 .dc.w MC2OBS-(MC2OBS/4)
3527 .dc.b MC2CFR0,MC2CFR1
3528 .dc.b 0,0
3529 .dc.b MC2DISC,0
3530 .dc.b 0,0
3531 .dc.w 0,0
3532
3533 .endc
3534
3535 .page
3536
3537| brtable -- Baud rate setup table
3538| ------- ---------------------
3539brtable: .dc.b BR_19K2 | 0 - 19200 baud
3540 .dc.b BR_9600 | 1 - 9600 baud
3541 .dc.b BR_4800 | 2 - 4800 baud
3542 .dc.b BR_3600 | 3 - 3600 baud
3543 .dc.b BR_2400 | 4 - 2400 baud
3544 .dc.b BR_7200 | 5 - 7200 baud (2000 on Atari)
3545 .dc.b BR_1800 | 6 - 1800 baud
3546 .dc.b BR_1200 | 7 - 1200 baud
3547 .dc.b BR_600 | 8 - 600 baud
3548 .dc.b BR_300 | 9 - 300 baud
3549
3550| iortab -- iorec pointer table
3551| ------ -------------------
3552iortab: .dc.l sr1iorec | 0 - PRT Serial-1 Printer
3553 .dc.l sr2iorec | 1 - AUX Serial-2 Host
3554 .dc.l sr2iorec | 2 - CON Serial-2 Console
3555
3556 .ifne BUCHLA
3557
3558 .dc.l mc1iorec | 3 - MC1 MIDI-1 MIDI port #1
3559 .dc.l mc2iorec | 4 - MC2 MIDI-2 MIDI port #2
3560
3561 .endc
3562
3563| aciatab -- iorec and ACIA pointer table
3564| ------- ----------------------------
3565aciatab: .dc.l sr1iorec,SR1ACIA | 0 - PRT Serial-1
3566 .dc.l sr2iorec,SR2ACIA | 1 - AUX Serial-2
3567 .dc.l sr2iorec,SR2ACIA | 2 - CON Serial-2
3568
3569 .ifne BUCHLA
3570
3571 .dc.l mc1iorec,MC1ACIA | 3 - MC1 MIDI-1
3572 .dc.l mc2iorec,MC2ACIA | 4 - MC2 MIDI-2
3573
3574 .endc
3575
3576 .page
3577
3578 .ifne BUCHLA
3579
3580| pbpbtab -- Prototype BPB data table (BPS..NHID) 19 bytes per entry
3581| ------- ---------------------------------------------------------
3582
3583| 0 -- 40 tracks, single sided (180K)
3584
3585pbpbtab: .dc.b 0x00,0x02,0x01,0x01,0x00,0x02,0x40,0x00
3586 .dc.b 0x68,0x01,0xFC,0x02,0x00,0x09,0x00,0x01
3587 .dc.b 0x00,0x00,0x00
3588
3589| 1 -- 40 tracks, double sided (360K)
3590
3591 .dc.b 0x00,0x02,0x02,0x01,0x00,0x02,0x70,0x00
3592 .dc.b 0xD0,0x02,0xFD,0x02,0x00,0x09,0x00,0x02
3593 .dc.b 0x00,0x00,0x00
3594
3595| 2 -- 80 tracks, single sided (360K)
3596
3597 .dc.b 0x00,0x02,0x02,0x01,0x00,0x02,0x70,0x00
3598 .dc.b 0xD0,0x02,0xF8,0x05,0x00,0x09,0x00,0x01
3599 .dc.b 0x00,0x00,0x00
3600
3601| 3 -- 80 tracks, double sided (720K)
3602
3603 .dc.b 0x00,0x02,0x02,0x01,0x00,0x02,0x70,0x00
3604 .dc.b 0xA0,0x05,0xF9,0x05,0x00,0x09,0x00,0x02
3605 .dc.b 0x00,0x00,0x00
3606
3607| VSDD initialization table
3608
3609 .even
3610
3611vsddtab: .dc.w 0x8252 | R0 Mode word 0
3612 .dc.w 0xE474 | R1 Mode word 1
3613 .dc.w 0x0006 | R2 Register window base
3614 .dc.w 0x0100 | R3 Data window base
3615 .dc.w 0x0000 | R4 Data length mask
3616 .dc.w 0x0000 | R5 Data segment base
3617 .dc.w 0x0001 | R6 Priority access count
3618 .dc.w 0x0040 | R7 ODT base
3619 .dc.w 0x0080 | R8 AT base
3620 .dc.w 0x0010 | R9 CLT base
3621 .dc.w 0x0011 | R10 CG bases
3622 .dc.w 0x0000 | R11 AT counter (R/O)
3623
3624 .dc.w 0x0C08 | R12 HC0 = 3, VC0 = 8
3625 .dc.w 0x140A | R13 HC1 = 5, VC1 = 10
3626 .dc.w 0x9568 | R14 HC2 = 37, VC2 = 360
3627 .dc.w 0xA16A | R15 HC3 = 40, VC3 = 362
3628
3629vsddit01: .dc.w 0x8253 | R0 with UCF = 1, DEN = 0
3630vsddit02: .dc.w 0x825B | R0 with UCF = 1, DEN = 1
3631
3632 .page
3633
3634| analog processor input state table
3635
3636api_tab: .dc.b 0,1,1,1,1,1,1,1,1,1 | 0..9
3637 .dc.b 1,1,1,1,1,1,1,1,1,1 | 10..19
3638 .dc.b 1,1,1,1,1 | 20..24
3639 .dc.b 3,3,3,3,3 | 25..29
3640 .dc.b 3,3,3,3,3,3,3,3,3 | 30..38
3641 .dc.b 5 | 39
3642 .dc.b 5,5,5,5,5,5,5,5,5,5 | 40..49
3643 .dc.b 5,5,5 | 50..52
3644 .dc.b 3,3,3,3,3,3,3 | 53..59
3645 .dc.b 5,5,5,5,5,5,5,5,5,5 | 60..69
3646 .dc.b 5,5,5 | 70..72
3647 .dc.b 6,6,6,6,6,6,6 | 73..79
3648 .dc.b 6,6,6 | 80..82
3649
3650 .even
3651
3652| analog processor state transfer vector
3653
3654api_tv: .dc.l api_s0,api_s1,api_s2,api_s3
3655 .dc.l api_s4,api_s5,api_s6
3656
3657 .endc
3658
3659 .page
3660|************************************************************************
3661| |
3662| RAM storage definitions |
3663| ----------------------- |
3664|************************************************************************
3665
3666 .bss
3667 .even
3668
3669| RAM data area
3670| -------------
3671| WARNING:
3672| --------
3673| The variables from timevec through rsarea are permanently assigned so
3674| that we can link to certain bios variables without having to link to the
3675| bios object file itself. Some of these get defined in hwdefs.s and in
3676| hwdefs.s so beware of changing them.
3677
3678timevec: .ds.l 1 | System timer trap vector
3679critvec: .ds.l 1 | Critical error handler vector
3680termvec: .ds.l 1 | Process terminate hook vector
3681resvec3: .ds.l 1 | Reserved vector 3
3682resvec4: .ds.l 1 | Reserved vector 4
3683resvec5: .ds.l 1 | Reserved vector 5
3684resvec6: .ds.l 1 | Reserved vector 6
3685resvec7: .ds.l 1 | Reserved vector 7
3686
3687fc_sw: .ds.w 1 | Frame clock switch (<0=dn, 0=off, >0=up)
3688fc_val: .ds.l 1 | Frame clock value (0..FCMAX)
3689
3690wzcrsh: .ds.w 1 | Crash area: flag for ROMP
3691crshsr: .ds.w 1 | Crash area: SR
3692crshpc: .ds.l 1 | Crash area: PC
3693crshsp: .ds.l 1 | Crash area: SP
3694crshus: .ds.l 1 | Crash area: USP
3695crshvc: .ds.l 1 | Crash area: vector # in MS byte
3696crshrg: .ds.l 16 | Crash area: registers
3697crshst: .ds.w 16 | Crash area: top 16 words of stack
3698
3699| The area from biosram to SSTACK-1 is cleared on reset.
3700| ------------------------------------------------------
3701biosram: | Start of BIOS RAM variables
3702
3703 .ifne BUCHLA
3704
3705hz_1k: .ds.l 1 | 1000 Hz clock
3706hz_200: .ds.l 1 | 200 Hz clock
3707frclock: .ds.l 1 | 50 Hz clock
3708t1count: .ds.w 1 | Timer 1 count
3709t2count: .ds.w 1 | Timer 2 count
3710t3count: .ds.w 1 | Timer 3 count
3711
3712seekrate: .ds.w 1 | Seek rate
3713cdev: .ds.w 1 | Current drive
3714ctrack: .ds.w 1 | Current track
3715csect: .ds.w 1 | Current sector
3716cside: .ds.w 1 | Current side
3717ccount: .ds.w 1 | Current sector count
3718spt: .ds.w 1 | Sectors per track
3719interlv: .ds.w 1 | Sector interleave count
3720virgin: .ds.w 1 | Initial formatting data
3721deferr: .ds.w 1 | Default error number
3722curerr: .ds.w 1 | Current error number
3723
3724cdma: .ds.l 1 | Current DMA address
3725edma: .ds.l 1 | Ending DMA address
3726tmpdma: .ds.l 1 | Temporary DMA address
3727
3728 .endc
3729
3730rseed: .ds.l 1 | Random number seed
3731
3732savptr: .ds.l 1 | Pointer to register save area
3733
3734rsflag: .ds.l 1 | Register save area overflow flag
3735 .ds.l 18*32 | Register save area (32 levels)
3736rsarea: .ds.l 1 | Dummy long word at top of save area
3737
3738| ***** end of the permanently assigned bios variables *****
3739
3740 .page
3741
3742 .ifne BUCHLA
3743
3744acctim: .ds.l 2 | Accumulated disk time table
3745maxactim: .ds.l 1 | Maximum acctim value
3746hdv_init: .ds.l 1 | Disk init vector
3747hdv_bpb: .ds.l 1 | Disk get bpb vector
3748hdv_rw: .ds.l 1 | Disk r/w vector
3749hdv_boot: .ds.l 1 | Disk boot vector
3750hdv_mchg: .ds.l 1 | Disk media change vector
3751drvbits: .ds.l 1 | Drive map bits
3752dskbufp: .ds.l 1 | Disk buffer pointer
3753 .page
3754nflops: .ds.w 1 | Number of drives
3755disknum: .ds.w 1 | Current disk number
3756booted: .ds.w 1 | Most recent boot device or -1
3757flock: .ds.w 1 | Floppy semaphore
3758fverify: .ds.w 1 | Floppy verify flag
3759
3760tdiv1: .ds.w 1 | Timer divider 1 (divides hz_1k)
3761tdiv2: .ds.w 1 | Timer divider 2 (divides hz_200)
3762
3763retrycnt: .ds.w 1 | Re-try count
3764wpstatus: .ds.w 1 | Write protect status table
3765wplatch: .ds.w 1 | Write protect latch table
3766bootdev: .ds.w 1 | Boot device number
3767
3768motoron: .ds.w 1 | Motor-on flag
3769deslflag: .ds.w 1 | Drive deselect flag
3770
3771 .endc
3772
3773flpsrsv: .ds.w 1 | Status register save area
3774flpregs: .ds.l 16 | Register save area
3775
3776 .ifne BUCHLA
3777
3778dsb0: .ds.l 1 | Drive A DSB
3779dsb1: .ds.l 1 | Drive B DSB
3780
3781dskmode: .ds.b 2 | Disk change mode table
3782dskerrs: .ds.w 2 | Disk error code table
3783drvbpbs: .ds.w 16*2 | Disk BPB save area
3784
3785 .endc
3786
3787 .page
3788
3789sr1iorec: .ds.b IORECLN | Serial-1 iorec structure
3790sr2iorec: .ds.b IORECLN | Serial-2 iorec structure
3791
3792 .ifne BUCHLA
3793
3794mc1iorec: .ds.b IORECLN | MIDI-1 iorec structure
3795mc2iorec: .ds.b IORECLN | MIDI-2 iorec structure
3796
3797 .endc
3798
3799sr1ibuf: .ds.b SR1IBS | Serial-1 input buffer
3800sr1obuf: .ds.b SR1OBS | Serial-1 output buffer
3801sr2ibuf: .ds.b SR2IBS | Serial-2 input buffer
3802sr2obuf: .ds.b SR2OBS | Serial-2 output buffer
3803
3804 .ifne BUCHLA
3805
3806mc1ibuf: .ds.b MC1IBS | MIDI-1 input buffer
3807mc1obuf: .ds.b MC1OBS | MIDI-1 output buffer
3808mc2ibuf: .ds.b MC2IBS | MIDI-2 input buffer
3809mc2obuf: .ds.b MC2OBS | MIDI-2 output buffer
3810
3811api_inp: .ds.b 1 | Analog processor input byte
3812api_bug: .ds.b 1 | Analog processor signal # "bug trap"
3813api_sv: .ds.b 1 | Analog processor state
3814api_svb: .ds.b 1 | Analog processor state "bug trap"
3815
3816 .even
3817
3818api_sig: .ds.b 1 | Analog signal number
3819api_val: .ds.b 1 | Analog value
3820
3821api_fi: .ds.l 1 | Analog processor FIFO input pointer
3822api_fo: .ds.l 1 | Analog processor FIFO output pointer
3823api_fum: .ds.w APISIZE | Analog processor FIFO
3824api_fe: | End of analog processor FIFO
3825
3826 .endc
3827
3828 .even
3829
3830basepage: .ds.l 64 | Pseudo base page
3831
3832buffer: .ds.b 1024 | Default disk buffer
3833
3834biostop: | End of BIOS RAM
3835
3836 .end
Note: See TracBrowser for help on using the repository browser.