source: buchla-68k/orig/MT/MTBIOS.S

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

Imported original source code.

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