source: buchla-68k/rom/bios.s

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

Fix symbol collisions.

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