source: buchla-68k/orig/ROM/BIOS.S@ 4f508e6

Last change on this file since 4f508e6 was 3ae31e9, checked in by Thomas Lopatic <thomas@…>, 8 years ago

Imported original source code.

  • Property mode set to 100755
File size: 108.9 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 .equ 18 * First part of version number
34VM2 .equ 0 * Second part of version number
35VDATE .equ $19880620 * Version date
36*
37BUCHLA .equ 1 * Non-Zero for Buchla 700, 0 for NASA
38NASASIO .equ 0 * Non-zero for NASA, 0 for Buchla addr.
39*
40FL_SKR .equ $00 * 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 .equ $0300 * IPL 3 value for sr
123IPL4 .equ $0400 * IPL 4 value for sr
124IPL7 .equ $0700 * IPL 7 value for sr (4 for debug)
125*
126 .ifne BUCHLA
127*
128INITIPL .equ IPL3+$2000 * Initial Internal Priority Level
129*
130 .endc
131*
132 .ifeq BUCHLA
133*
134INITIPL .equ IPL4+$2000 * Initial Internal Priority Level
135*
136 .endc
137*
138* Memory allocation
139* -----------------
140 .ifeq BUCHLA
141*
142TPA .equ $008000 * Put TPA 32K up from the bottom
143*
144 .endc
145*
146 .ifne BUCHLA
147*
148TPA .equ $010000 * Put TPA 64K up from the bottom
149*
150 .endc
151*
152SSTACK .equ TPA * Put system stack just below TPA
153*
154p_bbase .equ $0018 * Basepage offset to bss base
155p_blen .equ $001C * Basepage offset to bss length
156*
157* It's magic ...
158* --------------
159FMAGIC .equ $87654321 * Magic for formatting
160RETRYIT .equ $10000 * Magic for re-try from criter
161RSMAGIC .equ $78563412 * Magic for register save area OK
162*
163* Miscellaneous constants
164* -----------------------
165FCMAX .equ $00FFFFFF * Maximum frame counter value (24 bits)
166*
167 .page
168*
169* CFR0 Baud Rates:
170* ----------------
171BR_300 .equ $04
172BR_600 .equ $05
173BR_1200 .equ $06
174BR_1800 .equ $07
175BR_2400 .equ $08
176BR_3600 .equ $09
177BR_4800 .equ $0A
178BR_7200 .equ $0B
179BR_9600 .equ $0C
180BR_19K2 .equ $0D
181BR_EXT .equ $0F
182*
183* CFR0 Stop bits (includes TBR select bit):
184* -----------------------------------------
185NSB_1 .equ $40
186NSB_2 .equ $60
187*
188* CFR1 Number of Data Bits (includes MSB):
189* ----------------------------------------
190NDB_5 .equ $80
191NDB_6 .equ $A0
192NDB_7 .equ $C0
193NDB_8 .equ $E0
194*
195* CFR1 Parity Selection:
196* ----------------------
197P_ODD .equ $04
198P_EVEN .equ $0C
199P_MARK .equ $14
200P_SPACE .equ $1C
201*
202P_NONE .equ $00
203*
204* Line Discipline:
205* ----------------
206L_NUL .equ $00 * No protocol
207L_XON .equ $01 * XON/XOFF
208L_RTS .equ $02 * RTS/CTS
209*
210 .page
211*
212* I/O Buffer Sizes:
213* -----------------
214SR1IBS .equ 256
215SR1OBS .equ 256
216SR2IBS .equ 256
217SR2OBS .equ 256
218*
219 .ifne BUCHLA
220*
221MC1IBS .equ 512
222MC1OBS .equ 256
223MC2IBS .equ 512
224MC2OBS .equ 256
225*
226 .endc
227*
228* Line Disciplines:
229* -----------------
230SR1DISC .equ L_XON
231SR2DISC .equ L_XON
232*
233 .ifne BUCHLA
234*
235MC1DISC .equ L_NUL
236MC2DISC .equ L_NUL
237*
238 .endc
239*
240* CFR Setings:
241* ------------
242SR1CFR0 .equ BR_9600+NSB_1
243SR1CFR1 .equ NDB_8+P_NONE
244SR2CFR0 .equ BR_9600+NSB_1
245SR2CFR1 .equ NDB_8+P_NONE
246*
247 .ifne BUCHLA
248*
249MC1CFR0 .equ BR_EXT+NSB_1
250MC1CFR1 .equ NDB_8+P_NONE
251MC2CFR0 .equ BR_EXT+NSB_1
252MC2CFR1 .equ NDB_8+P_NONE
253*
254 .endc
255*
256 .page
257*
258* I/O Addresses:
259* --------------
260VSDDINIT .equ $200400 * VSDD initial register base address
261VSDDDATA .equ $200000 * VSDD data segment base address
262*
263 .ifeq BUCHLA
264*
265 .ifeq NASASIO
266*
267SR1ACIA .equ $3A8001 * Serial-1 ACIA base address (BUCHLA)
268SR2ACIA .equ $3A8009 * Serial-2 ACIA base address
269*
270 .endc
271*
272 .ifne NASASIO
273*
274SR1ACIA .equ $398001 * Serial-1 ACIA base address (NASA)
275SR2ACIA .equ $398009 * Serial-2 ACIA base address
276*
277 .endc
278*
279 .endc
280*
281 .ifne BUCHLA
282*
283FPUBASE .equ $180000 * FPU base address
284TIMER .equ $3A0001 * Timer base address
285LCD .equ $3A4001 * LCD driver base address
286SR1ACIA .equ $3A8001 * Serial-1 ACIA base address (BUCHLA)
287SR2ACIA .equ $3A8009 * Serial-2 ACIA base address
288MC1ACIA .equ $3AC001 * MIDI-1 ACIA base address
289MC2ACIA .equ $3AC009 * MIDI-2 ACIA base address
290FLOPPY .equ $3B0001 * Floppy controller base address
291PSG .equ $3B4001 * Sound chip base address
292LEDS .equ $3B8001 * LED driver base address
293ANALOG .equ $3BC001 * Analog processor base address
294*
295* FPU address offsets and misc. values
296*
297FPU_CTL .equ $4000 * FPU control
298*
299FPU_IN .equ $4000 * FPU input address
300FPU_CLR .equ $6000 * FPU interrupt reset address
301*
302FPU_RST .equ $0015 * FPU reset value
303*
304* PSG address offsets
305*
306PSG_RD .equ PSG * Read PSG data
307PSG_WL .equ PSG * Write PSG address latch
308PSG_WD .equ PSG+2 * Write PSG data
309*
310 .endc
311*
312* VSDD data structure offsets
313*
314VSDD_REG .equ VSDDDATA * Registers
315VSDD_AT .equ VSDDDATA+$0100 * Access Table
316*
317 .ifne BUCHLA
318*
319* Timer registers
320*
321TIME_CRX .equ TIMER * Control register 1 or 3
322TIME_CR2 .equ TIMER+2 * Control register 2
323TIME_T1H .equ TIMER+4 * Timer 1 high byte
324TIME_T1L .equ TIMER+6 * Timer 1 low byte
325TIME_T2H .equ TIMER+8 * Tiemr 2 high byte
326TIME_T2L .equ TIMER+10 * Timer 2 low byte
327TIME_T3H .equ TIMER+12 * Timer 3 high byte
328TIME_T3L .equ TIMER+14 * Timer 3 low byte
329*
330 .endc
331*
332* ACIA Register offsets:
333* ----------------------
334ACIA_IER .equ 0 * ACIA IER offset
335ACIA_ISR .equ 0 * ACIA ISR offset
336ACIA_CSR .equ 2 * ACIA CSR offset
337ACIA_CFR .equ 2 * ACIA CFR offset
338ACIA_TBR .equ 4 * ACIA TBR offset
339ACIA_TDR .equ 6 * ACIA TDR offset
340ACIA_RDR .equ 6 * ACIA RDR offset
341*
342 .page
343*
344 .ifne BUCHLA
345*
346* Floppy register offsets:
347* ------------------------
348DSKCMD .equ 0 * Command / status
349DSKTRK .equ 2 * Track
350DSKSEC .equ 4 * Sector
351DSKDAT .equ 6 * Data
352*
353* Miscellaneous equates:
354* ----------------------
355FL_NC .equ $02 * Non-compensated R/W/F bit
356*
357APISIZE .equ 256 * Analog processor buffer size
358*
359* Floppy commands:
360* ----------------
361FL_RS .equ $80 * Read sector
362FL_RM .equ $90 * Read multiple
363FL_WS .equ $A0 * Write sector
364FL_WT .equ $F0 * Write track (format)
365FL_FR .equ $D0 * Force reset
366FL_SK .equ $10 * Seek
367FL_SV .equ $14 * Seek w/verify
368*
369 .endc
370*
371 .page
372*
373* iorec structure definitions:
374* ----------------------------
375IORECLN .equ 40 * Length of an iorec structure
376*
377ibuf .equ 0 * Input buffer base address
378ibufsize .equ 4 * Input buffer size (bytes)
379ibufhd .equ 6 * Input buffer head index
380ibuftl .equ 8 * Input buffer tail index
381ibuflow .equ 10 * Input buffer low water mark
382ibufhi .equ 12 * Input buffer high water mark
383obuf .equ 14 * Output buffer base address
384obufsize .equ 18 * Output buffer size (bytes)
385obufhd .equ 20 * Output buffer head index
386obuftl .equ 22 * Output buffer tail index
387obuflow .equ 24 * Output buffer low water mark
388obufhi .equ 26 * Output buffer high water mark
389cfr0 .equ 28 * ACIA CFR, MS bit = 0
390cfr1 .equ 29 * ACIA CFR, MS bit = 1
391flagxon .equ 30 * XON flag (non-zero = XOFF sent)
392flagxoff .equ 31 * XOFF flag (non-zero = active)
393linedisc .equ 32 * Line discipline flags
394erbyte .equ 33 * Last error byte
395isr .equ 34 * ACIA ISR on interrupt
396csr .equ 35 * ACIA CSR on interrupt
397errct .equ 36 * Error count (FRM/OVR/BRK)
398ibfct .equ 38 * Input buffer full count
399*
400 .page
401*
402* Error codes:
403* ------------
404ERR01 .equ -1 * All purpose error
405ERR02 .equ -2 * Drive not ready
406ERR03 .equ -3 * Unknown command
407ERR04 .equ -4 * CRC Error
408ERR05 .equ -5 * Invalid request
409ERR06 .equ -6 * Seek error
410ERR07 .equ -7 * Unknown media
411ERR08 .equ -8 * Sector not found
412ERR09 .equ -9 * End of media (out of paper)
413ERR10 .equ -10 * Write fault
414ERR11 .equ -11 * Read fault
415ERR12 .equ -12 * General mishap
416ERR13 .equ -13 * Write protected
417ERR14 .equ -14 * Media changed
418ERR15 .equ -15 * Unknown device
419ERR16 .equ -16 * Bad sectors
420ERR17 .equ -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: dc.b '{Copyright 1988 by ' * Copyright message
440 dc.b 'D.N. Lynx Crowe}',0
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 #$2700,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 #$02000000,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 #$01000000,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,$0008 * Set bus error vector
481 move.l #nullrte,$0014 * Set divide error vector
482 move.l #nullrte,$0018 * Set CHK vector
483 move.l #nullrte,$001C * Set TRAPV vector
484 move.l #nullrte,$0024 * Set trace vector
485*
486 move.l #nullrte,$0030 * Set reserved vector 12
487 move.l #nullrte,$0034 * Set reserved vector 13
488 move.l #nullrte,$0038 * Set reserved vector 14
489*
490 move.l #nullrte,$003C * Set uninitialized int. vector
491*
492 move.l #nullrte,$0040 * Set reserved vector 16
493 move.l #nullrte,$0044 * Set reserved vector 17
494 move.l #nullrte,$0048 * Set reserved vector 18
495 move.l #nullrte,$004C * Set reserved vector 19
496 move.l #nullrte,$0050 * Set reserved vector 20
497 move.l #nullrte,$0054 * Set reserved vector 21
498 move.l #nullrte,$0058 * Set reserved vector 22
499 move.l #nullrte,$005C * Set reserved vector 23
500*
501 move.l #nullrte,$0060 * Set spurious int. vector
502*
503 move.l #serintr,$0074 * Set ACIA interrupt vector
504 move.l #nullrte,$0078 * Set level 6 vector
505 move.l #nullrte,$007C * Set level 7 vector
506*
507 move.l #trap13,$00B4 * Set trap13 vector
508 move.l #trap14,$00B8 * Set trap14 vector
509*
510 .page
511*
512 .ifne BUCHLA
513*
514 move.l #nullfpu,$0068 * Set FPU interrupt vector
515 move.l #api_int,$006C * Set analog trap vector
516 move.l #timeint,$0070 * 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 #$FFFF,fverify * Set read after write flag
525 move.w #FL_SKR,seekrate * Set default seek rate
526 move.w #$FFFF,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 #$80,PSG_WD * Write $80 (port B = output)
533 move.b #15,PSG_WL * Select PSG R15
534 move.b #$00,PSG_WD * Write $00 (sync enable)
535*
536 move.b #$00,TIME_T1H * Setup timer 1 (PLL)
537 move.b #$1F,TIME_T1L * ... for divide by 64
538 move.b #$0C,TIME_T2H * Setup timer 2 (FC)
539 move.b #$7F,TIME_T2L * ... for divide by 3200
540 move.b #$03,TIME_T3H * Setup timer 3 (RTC)
541 move.b #$20,TIME_T3L * ... for 1Ms interval
542 move.b #$42,TIME_CRX * Setup CR3
543 move.b #$41,TIME_CR2 * Setup CR2
544 move.b #$81,TIME_CRX * Setup CR1
545 move.b #$80,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 #$80,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 #$18,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 #$0000,$08(a0) * Set CV1 to 0
609 addq.w #1,d0 * Delay
610 addq.w #1,d0 * ...
611 move.w #$0000,$0A(a0) * Set SF1 to 0
612 addq.w #1,d0 * Delay
613 addq.w #1,d0 * ...
614 move.w #$0000,$0C(a0) * Set CV2 to 0
615 addq.w #1,d0 * Delay
616 addq.w #1,d0 * ...
617 move.w #$0000,$0E(a0) * Set SF2 to 0
618 addq.w #1,d0 * Delay
619 addq.w #1,d0 * ...
620 move.w #$0000,$10(a0) * Set CV3 to 0
621 addq.w #1,d0 * Delay
622 addq.w #1,d0 * ...
623 move.w #$0000,$12(a0) * Set SF3 to 0
624 addq.w #1,d0 * Delay
625 addq.w #1,d0 * ...
626 move.w #$8300,$02(a0) * Set new value '10' to -10.00
627 addq.w #1,d0 * Delay
628 addq.w #1,d0 * ...
629 move.w #$8300,$1C(a0) * Set new value '01' to -10.00
630 addq.w #1,d0 * Delay
631 addq.w #1,d0 * ...
632 move.w #$0001,$16(a0) * Set exponent for shortest time
633 addq.w #1,d0 * Delay
634 addq.w #1,d0 * ...
635 move.w #$FFF0,$14(a0) * Set mantissa for shortest time
636 addq.w #1,d0 * Delay
637 addq.w #1,d0 * ...
638 move.w #$0005,$00(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 #$000000FF,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 #$2700 * 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 #$FFFFFFFE,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 #$FFFF,_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 #$FFFF,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 #$FFFE,sr * Clear carry = OK
1068 bra rs_xnf * Go do XON/XOFF check
1069*
1070rs_mt: move.w (a7)+,sr * Restore status
1071 ori #$0001,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 #$11,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 #$FFFE,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 #$0001,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 #$FFFE,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 #$0001,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 #$11,d0 * Is this an XON ?
1356 bne serrx2 * Jump if not
1357*
1358 move.b #$00,flagxoff(a0) * Clear flagxoff
1359 bra sertxq * Done
1360*
1361serrx2: cmpi.b #$13,d0 * Is this an XOFF ?
1362 bne serrx3 * Jump if not
1363*
1364 move.b #$FF,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 #$FF,flagxon(a0) * Set the flag
1389 move.b #$13,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 #$0070,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 #$7F,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 #$C3,ACIA_IER(a1) * Enable TDRE, RDRF
1583 bra aciai_3 * Go return
1584*
1585aciai_2: move.b #$E3,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 $3F,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* ------- --------------------
1615_hdvini: 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 #$FF,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 #$FF,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 #$FF,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 #$FF00,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 #$40000,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 #$40000,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 #$1C,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 #$40000,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 #$5C,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 #$4E,d0 * Write $4E 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 $00 as sync
2436 bsr wmult * ...
2437 move.w #3-1,d1 * Set count = 3
2438 move.b #$F5,d0 * Write $F5's
2439 bsr wmult * ...
2440 move.b #$FE,(a2)+ * Write $FE (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 #$F7,(a2)+ * Write checksum code
2446 move.w #22-1,d1 * Set count = 22
2447 move.b #$4E,d0 * Write gap
2448 bsr wmult * ...
2449 move.w #12-1,d1 * Set count = 12
2450 clr.b d0 * Write $00 as sync
2451 bsr wmult * ...
2452 move.w #3-1,d1 * Set count = 3
2453 move.b #$F5,d0 * Write $F5's
2454 bsr wmult * ...
2455 move.b #$FB,(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 #$F7,(a2)+ * Write CRC code
2465 move.w #40-1,d1 * Set count = 40
2466 move.b #$4E,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 #$4E,d0 * Write final gap
2478 bsr wmult * ...
2479 move.l cdma(a5),a2 * Get buffer address
2480 move.l #$40000,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 #$44,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 #$40000,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 #$40000,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 #$1C,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 #$FF00,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 #$18,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 #$3,d0 * ...
2810 or.b d0,d6 * OR into command word
2811 move.l #$40000,d7 * Set timeout counter
2812 btst #7,DSKCMD(a6) * Motor on ?
2813 bne flopcm01 * Jump if so
2814*
2815 move.l #$60000,d7 * Set longer timeout count
2816*
2817flopcm01: move.b d6,DSKCMD(a6) * Write command from d6
2818*
2819 move.l #$1000,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 #$FE,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 #$FFFF,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 #$1234,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 #$BB40E62D,-(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 #$FFFFFF,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 #$1234,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 #$FFFFFF,d0 * > $FFFFFF
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 #$FF,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 #$1FE,d0 * Plus sector length
3149 cmp.l -4(a6),d0 * Done ?
3150 bhi protbt11 * Loop if not
3151*
3152 move.w #$1234,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 #$7F,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 #$80,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 #$80,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 #$80,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 $00,$02,$01,$01,$00,$02,$40,$00
3586 dc.b $68,$01,$FC,$02,$00,$09,$00,$01
3587 dc.b $00,$00,$00
3588*
3589* 1 -- 40 tracks, double sided (360K)
3590*
3591 dc.b $00,$02,$02,$01,$00,$02,$70,$00
3592 dc.b $D0,$02,$FD,$02,$00,$09,$00,$02
3593 dc.b $00,$00,$00
3594*
3595* 2 -- 80 tracks, single sided (360K)
3596*
3597 dc.b $00,$02,$02,$01,$00,$02,$70,$00
3598 dc.b $D0,$02,$F8,$05,$00,$09,$00,$01
3599 dc.b $00,$00,$00
3600*
3601* 3 -- 80 tracks, double sided (720K)
3602*
3603 dc.b $00,$02,$02,$01,$00,$02,$70,$00
3604 dc.b $A0,$05,$F9,$05,$00,$09,$00,$02
3605 dc.b $00,$00,$00
3606*
3607* VSDD initialization table
3608*
3609 .even
3610*
3611vsddtab: dc.w $8252 * R0 Mode word 0
3612 dc.w $E474 * R1 Mode word 1
3613 dc.w $0006 * R2 Register window base
3614 dc.w $0100 * R3 Data window base
3615 dc.w $0000 * R4 Data length mask
3616 dc.w $0000 * R5 Data segment base
3617 dc.w $0001 * R6 Priority access count
3618 dc.w $0040 * R7 ODT base
3619 dc.w $0080 * R8 AT base
3620 dc.w $0010 * R9 CLT base
3621 dc.w $0011 * R10 CG bases
3622 dc.w $0000 * R11 AT counter (R/O)
3623*
3624 dc.w $0C08 * R12 HC0 = 3, VC0 = 8
3625 dc.w $140A * R13 HC1 = 5, VC1 = 10
3626 dc.w $9568 * R14 HC2 = 37, VC2 = 360
3627 dc.w $A16A * R15 HC3 = 40, VC3 = 362
3628*
3629vsddit01: dc.w $8253 * R0 with UCF = 1, DEN = 0
3630vsddit02: dc.w $825B * 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*
3690_wzcrsh: ds.w 1 * Crash area: flag for ROMP
3691_crshsr: ds.w 1 * Crash area: SR
3692_crshpc: ds.l 1 * Crash area: PC
3693_crshsp: ds.l 1 * Crash area: SP
3694_crshus: ds.l 1 * Crash area: USP
3695_crshvc: ds.l 1 * Crash area: vector # in MS byte
3696_crshrg: ds.l 16 * Crash area: registers
3697_crshst: 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 .equ * * Start of BIOS RAM variables
3702*
3703 .ifne BUCHLA
3704*
3705_hz_1k: ds.l 1 * 1000 Hz clock
3706_hz_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*
3734_rsflag: 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 .equ * * 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 .equ * * End of BIOS RAM
3835*
3836 .end
Note: See TracBrowser for help on using the repository browser.