- Timestamp:
- 07/01/2017 02:34:46 PM (7 years ago)
- Branches:
- master
- Children:
- 08e1da1
- Parents:
- f40a309
- Location:
- rom
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
rom/bios.s
rf40a309 r4f508e6 1 ******************************************************************************** 2 * * 3 * bios.s -- BIOS for the Buchla 700 and NASA 3D Helmet Display * 4 * ------ -------------------------------------------------- * 5 * * 6 * See VM1,VM2 and VDATE for version and date * 7 * Written by D.N. Lynx Crowe * 8 * * 9 * Very loosely based on ideas from: * 10 * * 11 * "Atari ST Internals", by Abacus Software, * 12 * "A Hitchhiker's Guide to the BIOS", by Atari, * 13 * "DOS Technical Reference", by IBM, * 14 *"DOS/360", by IBM,15 * "CP/M" , by Digital Research, and, of course, * 16 * "Unix (tm)", by AT&T, et al. * 17 * * 18 * After all, Why re-invent the wheel? * 19 * * 20 * Some of the functions are the same as Ataris, but quite a few are different, * 21 * and our I/O configuration is much different, so BEWARE! Make no * 22 * assumptions, and read the documentation and comments very carefully. * 23 * * 24 * Especially watch out for the extended BIOS functions. Most of them * 25 * are nothing at all like the Atari / GEMDOS extended bios functions, * 26 * and even the ones that are similar have different numbers. * 27 ******************************************************************************** 28 * 1 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 2 | | 3 | bios.s -- BIOS for the Buchla 700 and NASA 3D Helmet Display | 4 | ------ -------------------------------------------------- | 5 | | 6 | See VM1,VM2 and VDATE for version and date | 7 | Written by D.N. Lynx Crowe | 8 | | 9 | Very loosely based on ideas from: | 10 | | 11 | "Atari ST Internals", by Abacus Software, | 12 | "A Hitchhiker's Guide to the BIOS", by Atari, | 13 | "DOS Technical Reference", by IBM, | 14 | "DOS/360", by IBM, 15 | "CP/M" , by Digital Research, and, of course, | 16 | "Unix (tm)", by AT&T, et al. | 17 | | 18 | After all, Why re-invent the wheel? | 19 | | 20 | Some of the functions are the same as Ataris, but quite a few are different, | 21 | and our I/O configuration is much different, so BEWARE! Make no | 22 | assumptions, and read the documentation and comments very carefully. | 23 | | 24 | Especially watch out for the extended BIOS functions. Most of them | 25 | are nothing at all like the Atari / GEMDOS extended bios functions, | 26 | and even the ones that are similar have different numbers. | 27 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 28 29 29 .text 30 * 31 *Version and date32 *----------------33 VM1 .equ 18 *First part of version number34 VM2 .equ 0 *Second part of version number35 VDATE .equ $19880620 *Version date36 * 37 BUCHLA .equ 1 *Non-Zero for Buchla 700, 0 for NASA38 NASASIO .equ 0 *Non-zero for NASA, 0 for Buchla addr.39 * 40 FL_SKR .equ $00 *Seek rate (WD1772, 6Ms/step)41 ************************************************************************* 42 * 43 .page 44 * 45 .xref start_ *Where ROMP starts46 .xref _errno *Start of ROMP bss space47 * 48 .xdef basepage *Pseudo base page for romp49 .xdef _rsflag *Register save area overflow flag50 * 30 31 | Version and date 32 | ---------------- 33 VM1 = 18 | First part of version number 34 VM2 = 0 | Second part of version number 35 VDATE = 0x19880620 | Version date 36 37 BUCHLA = 1 | Non-Zero for Buchla 700, 0 for NASA 38 NASASIO = 0 | Non-zero for NASA, 0 for Buchla addr. 39 40 FL_SKR = 0x00 | Seek rate (WD1772, 6Ms/step) 41 ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 42 43 .page 44 45 .xref start_ | Where ROMP starts 46 .xref _errno | Start of ROMP bss space 47 48 .xdef basepage | Pseudo base page for romp 49 .xdef _rsflag | Register save area overflow flag 50 51 51 .ifne BUCHLA 52 * 53 .xdef _hdvini *Disk init54 * 55 .endc 56 * 57 .xdef _wzcrsh *ROMP crash flag58 .xdef _crshvc *Crash vector59 .xdef _crshsr *Crash SR60 .xdef _crshpc *Crash PC61 .xdef _crshsp *Crash SP62 .xdef _crshus *Crash USP63 .xdef _crshrg *Crash SP registers64 .xdef _crshst *Crash top of stack65 * 66 .page 67 * 52 53 .xdef _hdvini | Disk init 54 55 .endc 56 57 .xdef _wzcrsh | ROMP crash flag 58 .xdef _crshvc | Crash vector 59 .xdef _crshsr | Crash SR 60 .xdef _crshpc | Crash PC 61 .xdef _crshsp | Crash SP 62 .xdef _crshus | Crash USP 63 .xdef _crshrg | Crash SP registers 64 .xdef _crshst | Crash top of stack 65 66 .page 67 68 68 .ifne BUCHLA 69 * 69 70 70 .xdef _hz_1k 71 71 .xdef _hz_200 … … 74 74 .xdef t2count 75 75 .xdef t3count 76 * 76 77 77 .xdef nflops 78 78 .xdef disknum … … 81 81 .xdef flock 82 82 .xdef fverify 83 * 83 84 84 .xdef retrycnt 85 85 .xdef wpstatus 86 86 .xdef wplatch 87 87 .xdef bootdev 88 * 88 89 89 .xdef cdev 90 90 .xdef ctrack … … 92 92 .xdef cside 93 93 .xdef ccount 94 * 94 95 95 .xdef cdma 96 96 .xdef edma 97 97 .xdef tmpdma 98 98 .xdef rseed 99 * 99 100 100 .xdef savptr 101 * 101 102 102 .xdef flpsrsv 103 103 .xdef flpregs 104 * 104 105 105 .xdef dsb0 106 106 .xdef dsb1 107 * 107 108 108 .xdef dskmode 109 109 .xdef dskerrs 110 110 .xdef drvbpbs 111 * 112 .endc 113 * 111 112 .endc 113 114 114 .xdef biostop 115 * 116 .page 117 * 118 *Some critical equates:119 *----------------------120 *Interrupt masks121 *---------------122 IPL3 .equ $0300 *IPL 3 value for sr123 IPL4 .equ $0400 *IPL 4 value for sr124 IPL7 .equ $0700 *IPL 7 value for sr (4 for debug)125 * 115 116 .page 117 118 | Some critical equates: 119 | ---------------------- 120 | Interrupt masks 121 | --------------- 122 IPL3 = 0x0300 | IPL 3 value for sr 123 IPL4 = 0x0400 | IPL 4 value for sr 124 IPL7 = 0x0700 | IPL 7 value for sr (4 for debug) 125 126 126 .ifne BUCHLA 127 * 128 INITIPL .equ IPL3+$2000 *Initial Internal Priority Level129 * 130 .endc 131 * 127 128 INITIPL = IPL3+0x2000 | Initial Internal Priority Level 129 130 .endc 131 132 132 .ifeq BUCHLA 133 * 134 INITIPL .equ IPL4+$2000 *Initial Internal Priority Level135 * 136 .endc 137 * 138 *Memory allocation139 *-----------------133 134 INITIPL = IPL4+0x2000 | Initial Internal Priority Level 135 136 .endc 137 138 | Memory allocation 139 | ----------------- 140 140 .ifeq BUCHLA 141 * 142 TPA .equ $008000 *Put TPA 32K up from the bottom143 * 144 .endc 145 * 141 142 TPA = 0x008000 | Put TPA 32K up from the bottom 143 144 .endc 145 146 146 .ifne BUCHLA 147 * 148 TPA .equ $010000 *Put TPA 64K up from the bottom149 * 150 .endc 151 * 152 SSTACK .equ TPA *Put system stack just below TPA153 * 154 p_bbase .equ $0018 *Basepage offset to bss base155 p_blen .equ $001C *Basepage offset to bss length156 * 157 *It's magic ...158 *--------------159 FMAGIC .equ $87654321 *Magic for formatting160 RETRYIT .equ $10000 *Magic for re-try from criter161 RSMAGIC .equ $78563412 *Magic for register save area OK162 * 163 *Miscellaneous constants164 *-----------------------165 FCMAX .equ $00FFFFFF *Maximum frame counter value (24 bits)166 * 167 .page 168 * 169 *CFR0 Baud Rates:170 *----------------171 BR_300 .equ $04172 BR_600 .equ $05173 BR_1200 .equ $06174 BR_1800 .equ $07175 BR_2400 .equ $08176 BR_3600 .equ $09177 BR_4800 .equ $0A178 BR_7200 .equ $0B179 BR_9600 .equ $0C180 BR_19K2 .equ $0D181 BR_EXT .equ $0F182 * 183 *CFR0 Stop bits (includes TBR select bit):184 *-----------------------------------------185 NSB_1 .equ $40186 NSB_2 .equ $60187 * 188 *CFR1 Number of Data Bits (includes MSB):189 *----------------------------------------190 NDB_5 .equ $80191 NDB_6 .equ $A0192 NDB_7 .equ $C0193 NDB_8 .equ $E0194 * 195 *CFR1 Parity Selection:196 *----------------------197 P_ODD .equ $04198 P_EVEN .equ $0C199 P_MARK .equ $14200 P_SPACE .equ $1C201 * 202 P_NONE .equ $00203 * 204 *Line Discipline:205 *----------------206 L_NUL .equ $00 *No protocol207 L_XON .equ $01 *XON/XOFF208 L_RTS .equ $02 *RTS/CTS209 * 210 .page 211 * 212 *I/O Buffer Sizes:213 *-----------------214 SR1IBS .equ256215 SR1OBS .equ256216 SR2IBS .equ256217 SR2OBS .equ256218 * 147 148 TPA = 0x010000 | Put TPA 64K up from the bottom 149 150 .endc 151 152 SSTACK = TPA | Put system stack just below TPA 153 154 p_bbase = 0x0018 | Basepage offset to bss base 155 p_blen = 0x001C | Basepage offset to bss length 156 157 | It's magic ... 158 | -------------- 159 FMAGIC = 0x87654321 | Magic for formatting 160 RETRYIT = 0x10000 | Magic for re-try from criter 161 RSMAGIC = 0x78563412 | Magic for register save area OK 162 163 | Miscellaneous constants 164 | ----------------------- 165 FCMAX = 0x00FFFFFF | Maximum frame counter value (24 bits) 166 167 .page 168 169 | CFR0 Baud Rates: 170 | ---------------- 171 BR_300 = 0x04 172 BR_600 = 0x05 173 BR_1200 = 0x06 174 BR_1800 = 0x07 175 BR_2400 = 0x08 176 BR_3600 = 0x09 177 BR_4800 = 0x0A 178 BR_7200 = 0x0B 179 BR_9600 = 0x0C 180 BR_19K2 = 0x0D 181 BR_EXT = 0x0F 182 183 | CFR0 Stop bits (includes TBR select bit): 184 | ----------------------------------------- 185 NSB_1 = 0x40 186 NSB_2 = 0x60 187 188 | CFR1 Number of Data Bits (includes MSB): 189 | ---------------------------------------- 190 NDB_5 = 0x80 191 NDB_6 = 0xA0 192 NDB_7 = 0xC0 193 NDB_8 = 0xE0 194 195 | CFR1 Parity Selection: 196 | ---------------------- 197 P_ODD = 0x04 198 P_EVEN = 0x0C 199 P_MARK = 0x14 200 P_SPACE = 0x1C 201 202 P_NONE = 0x00 203 204 | Line Discipline: 205 | ---------------- 206 L_NUL = 0x00 | No protocol 207 L_XON = 0x01 | XON/XOFF 208 L_RTS = 0x02 | RTS/CTS 209 210 .page 211 212 | I/O Buffer Sizes: 213 | ----------------- 214 SR1IBS = 256 215 SR1OBS = 256 216 SR2IBS = 256 217 SR2OBS = 256 218 219 219 .ifne BUCHLA 220 * 221 MC1IBS .equ512222 MC1OBS .equ256223 MC2IBS .equ512224 MC2OBS .equ256225 * 226 .endc 227 * 228 *Line Disciplines:229 *-----------------230 SR1DISC .equL_XON231 SR2DISC .equL_XON232 * 220 221 MC1IBS = 512 222 MC1OBS = 256 223 MC2IBS = 512 224 MC2OBS = 256 225 226 .endc 227 228 | Line Disciplines: 229 | ----------------- 230 SR1DISC = L_XON 231 SR2DISC = L_XON 232 233 233 .ifne BUCHLA 234 * 235 MC1DISC .equL_NUL236 MC2DISC .equL_NUL237 * 238 .endc 239 * 240 *CFR Setings:241 *------------242 SR1CFR0 .equBR_9600+NSB_1243 SR1CFR1 .equNDB_8+P_NONE244 SR2CFR0 .equBR_9600+NSB_1245 SR2CFR1 .equNDB_8+P_NONE246 * 234 235 MC1DISC = L_NUL 236 MC2DISC = L_NUL 237 238 .endc 239 240 | CFR Setings: 241 | ------------ 242 SR1CFR0 = BR_9600+NSB_1 243 SR1CFR1 = NDB_8+P_NONE 244 SR2CFR0 = BR_9600+NSB_1 245 SR2CFR1 = NDB_8+P_NONE 246 247 247 .ifne BUCHLA 248 * 249 MC1CFR0 .equBR_EXT+NSB_1250 MC1CFR1 .equNDB_8+P_NONE251 MC2CFR0 .equBR_EXT+NSB_1252 MC2CFR1 .equNDB_8+P_NONE253 * 254 .endc 255 * 256 .page 257 * 258 *I/O Addresses:259 *--------------260 VSDDINIT .equ $200400 *VSDD initial register base address261 VSDDDATA .equ $200000 *VSDD data segment base address262 * 248 249 MC1CFR0 = BR_EXT+NSB_1 250 MC1CFR1 = NDB_8+P_NONE 251 MC2CFR0 = BR_EXT+NSB_1 252 MC2CFR1 = NDB_8+P_NONE 253 254 .endc 255 256 .page 257 258 | I/O Addresses: 259 | -------------- 260 VSDDINIT = 0x200400 | VSDD initial register base address 261 VSDDDATA = 0x200000 | VSDD data segment base address 262 263 263 .ifeq BUCHLA 264 * 264 265 265 .ifeq NASASIO 266 * 267 SR1ACIA .equ $3A8001 *Serial-1 ACIA base address (BUCHLA)268 SR2ACIA .equ $3A8009 *Serial-2 ACIA base address269 * 270 .endc 271 * 266 267 SR1ACIA = 0x3A8001 | Serial-1 ACIA base address (BUCHLA) 268 SR2ACIA = 0x3A8009 | Serial-2 ACIA base address 269 270 .endc 271 272 272 .ifne NASASIO 273 * 274 SR1ACIA .equ $398001 *Serial-1 ACIA base address (NASA)275 SR2ACIA .equ $398009 *Serial-2 ACIA base address276 * 277 .endc 278 * 279 .endc 280 * 273 274 SR1ACIA = 0x398001 | Serial-1 ACIA base address (NASA) 275 SR2ACIA = 0x398009 | Serial-2 ACIA base address 276 277 .endc 278 279 .endc 280 281 281 .ifne BUCHLA 282 * 283 FPUBASE .equ $180000 *FPU base address284 TIMER .equ $3A0001 *Timer base address285 LCD .equ $3A4001 *LCD driver base address286 SR1ACIA .equ $3A8001 *Serial-1 ACIA base address (BUCHLA)287 SR2ACIA .equ $3A8009 *Serial-2 ACIA base address288 MC1ACIA .equ $3AC001 *MIDI-1 ACIA base address289 MC2ACIA .equ $3AC009 *MIDI-2 ACIA base address290 FLOPPY .equ $3B0001 *Floppy controller base address291 PSG .equ $3B4001 *Sound chip base address292 LEDS .equ $3B8001 *LED driver base address293 ANALOG .equ $3BC001 *Analog processor base address294 * 295 *FPU address offsets and misc. values296 * 297 FPU_CTL .equ $4000 *FPU control298 * 299 FPU_IN .equ $4000 *FPU input address300 FPU_CLR .equ $6000 *FPU interrupt reset address301 * 302 FPU_RST .equ $0015 *FPU reset value303 * 304 *PSG address offsets305 * 306 PSG_RD .equ PSG *Read PSG data307 PSG_WL .equ PSG *Write PSG address latch308 PSG_WD .equ PSG+2 *Write PSG data309 * 310 .endc 311 * 312 *VSDD data structure offsets313 * 314 VSDD_REG .equ VSDDDATA *Registers315 VSDD_AT .equ VSDDDATA+$0100 *Access Table316 * 282 283 FPUBASE = 0x180000 | FPU base address 284 TIMER = 0x3A0001 | Timer base address 285 LCD = 0x3A4001 | LCD driver base address 286 SR1ACIA = 0x3A8001 | Serial-1 ACIA base address (BUCHLA) 287 SR2ACIA = 0x3A8009 | Serial-2 ACIA base address 288 MC1ACIA = 0x3AC001 | MIDI-1 ACIA base address 289 MC2ACIA = 0x3AC009 | MIDI-2 ACIA base address 290 FLOPPY = 0x3B0001 | Floppy controller base address 291 PSG = 0x3B4001 | Sound chip base address 292 LEDS = 0x3B8001 | LED driver base address 293 ANALOG = 0x3BC001 | Analog processor base address 294 295 | FPU address offsets and misc. values 296 297 FPU_CTL = 0x4000 | FPU control 298 299 FPU_IN = 0x4000 | FPU input address 300 FPU_CLR = 0x6000 | FPU interrupt reset address 301 302 FPU_RST = 0x0015 | FPU reset value 303 304 | PSG address offsets 305 306 PSG_RD = PSG | Read PSG data 307 PSG_WL = PSG | Write PSG address latch 308 PSG_WD = PSG+2 | Write PSG data 309 310 .endc 311 312 | VSDD data structure offsets 313 314 VSDD_REG = VSDDDATA | Registers 315 VSDD_AT = VSDDDATA+0x0100 | Access Table 316 317 317 .ifne BUCHLA 318 * 319 *Timer registers320 * 321 TIME_CRX .equ TIMER *Control register 1 or 3322 TIME_CR2 .equ TIMER+2 *Control register 2323 TIME_T1H .equ TIMER+4 *Timer 1 high byte324 TIME_T1L .equ TIMER+6 *Timer 1 low byte325 TIME_T2H .equ TIMER+8 *Tiemr 2 high byte326 TIME_T2L .equ TIMER+10 *Timer 2 low byte327 TIME_T3H .equ TIMER+12 *Timer 3 high byte328 TIME_T3L .equ TIMER+14 *Timer 3 low byte329 * 330 .endc 331 * 332 *ACIA Register offsets:333 *----------------------334 ACIA_IER .equ 0 *ACIA IER offset335 ACIA_ISR .equ 0 *ACIA ISR offset336 ACIA_CSR .equ 2 *ACIA CSR offset337 ACIA_CFR .equ 2 *ACIA CFR offset338 ACIA_TBR .equ 4 *ACIA TBR offset339 ACIA_TDR .equ 6 *ACIA TDR offset340 ACIA_RDR .equ 6 *ACIA RDR offset341 * 342 .page 343 * 318 319 | Timer registers 320 321 TIME_CRX = TIMER | Control register 1 or 3 322 TIME_CR2 = TIMER+2 | Control register 2 323 TIME_T1H = TIMER+4 | Timer 1 high byte 324 TIME_T1L = TIMER+6 | Timer 1 low byte 325 TIME_T2H = TIMER+8 | Tiemr 2 high byte 326 TIME_T2L = TIMER+10 | Timer 2 low byte 327 TIME_T3H = TIMER+12 | Timer 3 high byte 328 TIME_T3L = TIMER+14 | Timer 3 low byte 329 330 .endc 331 332 | ACIA Register offsets: 333 | ---------------------- 334 ACIA_IER = 0 | ACIA IER offset 335 ACIA_ISR = 0 | ACIA ISR offset 336 ACIA_CSR = 2 | ACIA CSR offset 337 ACIA_CFR = 2 | ACIA CFR offset 338 ACIA_TBR = 4 | ACIA TBR offset 339 ACIA_TDR = 6 | ACIA TDR offset 340 ACIA_RDR = 6 | ACIA RDR offset 341 342 .page 343 344 344 .ifne BUCHLA 345 * 346 *Floppy register offsets:347 *------------------------348 DSKCMD .equ 0 *Command / status349 DSKTRK .equ 2 *Track350 DSKSEC .equ 4 *Sector351 DSKDAT .equ 6 *Data352 * 353 *Miscellaneous equates:354 *----------------------355 FL_NC .equ $02 *Non-compensated R/W/F bit356 * 357 APISIZE .equ 256 *Analog processor buffer size358 * 359 *Floppy commands:360 *----------------361 FL_RS .equ $80 *Read sector362 FL_RM .equ $90 *Read multiple363 FL_WS .equ $A0 *Write sector364 FL_WT .equ $F0 *Write track (format)365 FL_FR .equ $D0 *Force reset366 FL_SK .equ $10 *Seek367 FL_SV .equ $14 *Seek w/verify368 * 369 .endc 370 * 371 .page 372 * 373 *iorec structure definitions:374 *----------------------------375 IORECLN .equ 40 *Length of an iorec structure376 * 377 ibuf .equ 0 *Input buffer base address378 ibufsize .equ 4 *Input buffer size (bytes)379 ibufhd .equ 6 *Input buffer head index380 ibuftl .equ 8 *Input buffer tail index381 ibuflow .equ 10 *Input buffer low water mark382 ibufhi .equ 12 *Input buffer high water mark383 obuf .equ 14 *Output buffer base address384 obufsize .equ 18 *Output buffer size (bytes)385 obufhd .equ 20 *Output buffer head index386 obuftl .equ 22 *Output buffer tail index387 obuflow .equ 24 *Output buffer low water mark388 obufhi .equ 26 *Output buffer high water mark389 cfr0 .equ 28 *ACIA CFR, MS bit = 0390 cfr1 .equ 29 *ACIA CFR, MS bit = 1391 flagxon .equ 30 *XON flag (non-zero = XOFF sent)392 flagxoff .equ 31 *XOFF flag (non-zero = active)393 linedisc .equ 32 *Line discipline flags394 erbyte .equ 33 *Last error byte395 isr .equ 34 *ACIA ISR on interrupt396 csr .equ 35 *ACIA CSR on interrupt397 errct .equ 36 *Error count (FRM/OVR/BRK)398 ibfct .equ 38 *Input buffer full count399 * 400 .page 401 * 402 *Error codes:403 *------------404 ERR01 .equ -1 *All purpose error405 ERR02 .equ -2 *Drive not ready406 ERR03 .equ -3 *Unknown command407 ERR04 .equ -4 *CRC Error408 ERR05 .equ -5 *Invalid request409 ERR06 .equ -6 *Seek error410 ERR07 .equ -7 *Unknown media411 ERR08 .equ -8 *Sector not found412 ERR09 .equ -9 *End of media (out of paper)413 ERR10 .equ -10 *Write fault414 ERR11 .equ -11 *Read fault415 ERR12 .equ -12 *General mishap416 ERR13 .equ -13 *Write protected417 ERR14 .equ -14 *Media changed418 ERR15 .equ -15 *Unknown device419 ERR16 .equ -16 *Bad sectors420 ERR17 .equ -17 *Insert disk421 * 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 * 431 begin: bra.s biosinit *Jump to bios init432 * 433 vermsg: dc.b VM1,VM2 *Version number434 * 435 dc.l biosinit *Reset address (bios init)436 * 437 created: dc.l VDATE *Creation date438 * 439 copyrite: dc.b '{Copyright 1988 by ' *Copyright message440 dc.b 'D.N. Lynx Crowe}',0441 * 442 dc.l 0 *Some padding443 * 345 346 | Floppy register offsets: 347 | ------------------------ 348 DSKCMD = 0 | Command / status 349 DSKTRK = 2 | Track 350 DSKSEC = 4 | Sector 351 DSKDAT = 6 | Data 352 353 | Miscellaneous equates: 354 | ---------------------- 355 FL_NC = 0x02 | Non-compensated R/W/F bit 356 357 APISIZE = 256 | Analog processor buffer size 358 359 | Floppy commands: 360 | ---------------- 361 FL_RS = 0x80 | Read sector 362 FL_RM = 0x90 | Read multiple 363 FL_WS = 0xA0 | Write sector 364 FL_WT = 0xF0 | Write track (format) 365 FL_FR = 0xD0 | Force reset 366 FL_SK = 0x10 | Seek 367 FL_SV = 0x14 | Seek w/verify 368 369 .endc 370 371 .page 372 373 | iorec structure definitions: 374 | ---------------------------- 375 IORECLN = 40 | Length of an iorec structure 376 377 ibuf = 0 | Input buffer base address 378 ibufsize = 4 | Input buffer size (bytes) 379 ibufhd = 6 | Input buffer head index 380 ibuftl = 8 | Input buffer tail index 381 ibuflow = 10 | Input buffer low water mark 382 ibufhi = 12 | Input buffer high water mark 383 obuf = 14 | Output buffer base address 384 obufsize = 18 | Output buffer size (bytes) 385 obufhd = 20 | Output buffer head index 386 obuftl = 22 | Output buffer tail index 387 obuflow = 24 | Output buffer low water mark 388 obufhi = 26 | Output buffer high water mark 389 cfr0 = 28 | ACIA CFR, MS bit = 0 390 cfr1 = 29 | ACIA CFR, MS bit = 1 391 flagxon = 30 | XON flag (non-zero = XOFF sent) 392 flagxoff = 31 | XOFF flag (non-zero = active) 393 linedisc = 32 | Line discipline flags 394 erbyte = 33 | Last error byte 395 isr = 34 | ACIA ISR on interrupt 396 csr = 35 | ACIA CSR on interrupt 397 errct = 36 | Error count (FRM/OVR/BRK) 398 ibfct = 38 | Input buffer full count 399 400 .page 401 402 | Error codes: 403 | ------------ 404 ERR01 = -1 | All purpose error 405 ERR02 = -2 | Drive not ready 406 ERR03 = -3 | Unknown command 407 ERR04 = -4 | CRC Error 408 ERR05 = -5 | Invalid request 409 ERR06 = -6 | Seek error 410 ERR07 = -7 | Unknown media 411 ERR08 = -8 | Sector not found 412 ERR09 = -9 | End of media (out of paper) 413 ERR10 = -10 | Write fault 414 ERR11 = -11 | Read fault 415 ERR12 = -12 | General mishap 416 ERR13 = -13 | Write protected 417 ERR14 = -14 | Media changed 418 ERR15 = -15 | Unknown device 419 ERR16 = -16 | Bad sectors 420 ERR17 = -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 431 begin: bra.s biosinit | Jump to bios init 432 433 vermsg: dc.b VM1,VM2 | Version number 434 435 dc.l biosinit | Reset address (bios init) 436 437 created: dc.l VDATE | Creation date 438 439 copyrite: dc.b "{Copyright 1988 by " | Copyright message 440 dc.b "D.N. Lynx Crowe}",0 441 442 dc.l 0 | Some padding 443 444 444 .page 445 445 .even 446 * 447 *biosinit -- Setup the defaults for the BIOS448 *-------- -------------------------------449 biosinit: move.w # $2700,sr *Set sup mode, no interrupts450 move.l #SSTACK,a7 *Setup supervisor stack pointer451 * 452 lea badtrap,a1 *Set default trap vector453 adda.l # $02000000,a1 *... with trap # in 31..24454 lea 8,a0 *... for traps 2..255446 447 | biosinit -- Setup the defaults for the BIOS 448 | -------- ------------------------------- 449 biosinit: move.w #0x2700,sr | Set sup mode, no interrupts 450 move.l #SSTACK,a7 | Setup supervisor stack pointer 451 452 lea badtrap,a1 | Set default trap vector 453 adda.l #0x02000000,a1 | ... with trap # in 31..24 454 lea 8,a0 | ... for traps 2..255 455 455 move.l #253,d1 456 * 457 binit1: move.l a1,(a0)+ *Store trap vector458 adda.l # $01000000,a1 *Increment trap #459 dbf d1,binit1 *Loop until done460 * 461 lea biosram,a0 *Clear BIOS ram ...462 lea SSTACK-2,a1 *... from biosram to SSTACK-1463 * 464 binit2: move.w #0,(a0)+ *Zero a word465 cmpa.l a0,a1 *Last one ?466 bne binit2 *Loop if not467 * 468 move.l #rsarea,savptr *Setup pointer to register area469 move.l #RSMAGIC,_rsflag *Set magic in _rsflag470 * 471 move.l #nullrts,timevec *Set timer interrupt vector472 move.l #nullrts,critvec *Set critical error vector473 move.l #nullrts,termvec *Set process terminate vector474 move.l #nullrts,resvec3 *Set software vector 3475 move.l #nullrts,resvec4 *Set software vector 4476 move.l #nullrts,resvec5 *Set software vector 5477 move.l #nullrts,resvec6 *Set software vector 6478 move.l #nullrts,resvec7 *Set software vector 7479 * 480 move.l #hardhlt, $0008 *Set bus error vector481 move.l #nullrte, $0014 *Set divide error vector482 move.l #nullrte, $0018 *Set CHK vector483 move.l #nullrte, $001C *Set TRAPV vector484 move.l #nullrte, $0024 *Set trace vector485 * 486 move.l #nullrte, $0030 *Set reserved vector 12487 move.l #nullrte, $0034 *Set reserved vector 13488 move.l #nullrte, $0038 *Set reserved vector 14489 * 490 move.l #nullrte, $003C *Set uninitialized int. vector491 * 492 move.l #nullrte, $0040 *Set reserved vector 16493 move.l #nullrte, $0044 *Set reserved vector 17494 move.l #nullrte, $0048 *Set reserved vector 18495 move.l #nullrte, $004C *Set reserved vector 19496 move.l #nullrte, $0050 *Set reserved vector 20497 move.l #nullrte, $0054 *Set reserved vector 21498 move.l #nullrte, $0058 *Set reserved vector 22499 move.l #nullrte, $005C *Set reserved vector 23500 * 501 move.l #nullrte, $0060 *Set spurious int. vector502 * 503 move.l #serintr, $0074 *Set ACIA interrupt vector504 move.l #nullrte, $0078 *Set level 6 vector505 move.l #nullrte, $007C *Set level 7 vector506 * 507 move.l #trap13, $00B4 *Set trap13 vector508 move.l #trap14, $00B8 *Set trap14 vector509 * 510 .page 511 * 456 457 binit1: 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 464 binit2: move.w #0,(a0)+ | Zero a word 465 cmpa.l a0,a1 | Last one ? 466 bne binit2 | Loop if not 467 468 move.l #rsarea,savptr | Setup pointer to register area 469 move.l #RSMAGIC,_rsflag | Set magic in _rsflag 470 471 move.l #nullrts,timevec | Set timer interrupt vector 472 move.l #nullrts,critvec | Set critical error vector 473 move.l #nullrts,termvec | Set process terminate vector 474 move.l #nullrts,resvec3 | Set software vector 3 475 move.l #nullrts,resvec4 | Set software vector 4 476 move.l #nullrts,resvec5 | Set software vector 5 477 move.l #nullrts,resvec6 | Set software vector 6 478 move.l #nullrts,resvec7 | Set software vector 7 479 480 move.l #hardhlt,0x0008 | Set bus error vector 481 move.l #nullrte,0x0014 | Set divide error vector 482 move.l #nullrte,0x0018 | Set CHK vector 483 move.l #nullrte,0x001C | Set TRAPV vector 484 move.l #nullrte,0x0024 | Set trace vector 485 486 move.l #nullrte,0x0030 | Set reserved vector 12 487 move.l #nullrte,0x0034 | Set reserved vector 13 488 move.l #nullrte,0x0038 | Set reserved vector 14 489 490 move.l #nullrte,0x003C | Set uninitialized int. vector 491 492 move.l #nullrte,0x0040 | Set reserved vector 16 493 move.l #nullrte,0x0044 | Set reserved vector 17 494 move.l #nullrte,0x0048 | Set reserved vector 18 495 move.l #nullrte,0x004C | Set reserved vector 19 496 move.l #nullrte,0x0050 | Set reserved vector 20 497 move.l #nullrte,0x0054 | Set reserved vector 21 498 move.l #nullrte,0x0058 | Set reserved vector 22 499 move.l #nullrte,0x005C | Set reserved vector 23 500 501 move.l #nullrte,0x0060 | Set spurious int. vector 502 503 move.l #serintr,0x0074 | Set ACIA interrupt vector 504 move.l #nullrte,0x0078 | Set level 6 vector 505 move.l #nullrte,0x007C | Set level 7 vector 506 507 move.l #trap13,0x00B4 | Set trap13 vector 508 move.l #trap14,0x00B8 | Set trap14 vector 509 510 .page 511 512 512 .ifne BUCHLA 513 * 514 move.l #nullfpu, $0068 *Set FPU interrupt vector515 move.l #api_int, $006C *Set analog trap vector516 move.l #timeint, $0070 *Set timer trap vector517 * 518 move.l #_hdvini,hdv_init *Set disk init vector519 move.l #getbpb,hdv_bpb *Set get BPB vector520 move.l #rwabs,hdv_rw *Set disk I/O vector521 move.l #bootload,hdv_boot *Setup boot load vector522 move.l #mediach,hdv_mchg *Setup media change vector523 * 524 move.w # $FFFF,fverify *Set read after write flag525 move.w #FL_SKR,seekrate *Set default seek rate526 move.w # $FFFF,booted *Say we're not booted yet527 move.l #buffer,dskbufp *Setup default disk buffer528 * 529 .page 530 * 531 move.b #7,PSG_WL *Select PSG R7532 move.b # $80,PSG_WD * Write $80 (port B = output)533 move.b #15,PSG_WL *Select PSG R15534 move.b # $00,PSG_WD * Write $00 (sync enable)535 * 536 move.b # $00,TIME_T1H *Setup timer 1 (PLL)537 move.b # $1F,TIME_T1L *... for divide by 64538 move.b # $0C,TIME_T2H *Setup timer 2 (FC)539 move.b # $7F,TIME_T2L *... for divide by 3200540 move.b # $03,TIME_T3H *Setup timer 3 (RTC)541 move.b # $20,TIME_T3L *... for 1Ms interval542 move.b # $42,TIME_CRX *Setup CR3543 move.b # $41,TIME_CR2 *Setup CR2544 move.b # $81,TIME_CRX *Setup CR1545 move.b # $80,TIME_CRX *Start the timers546 * 547 .endc 548 * 549 lea sr1iorec,a0 *Serial-1 iorec address to a0550 lea SR1ACIA,a1 *Serial-1 ACIA address to a1551 lea sr1dflt,a2 *Serial-1 dflt table addr to a2552 bsr.w aciainit *Go initialize the port553 * 554 lea sr2iorec,a0 *Serial-2 iorec address to a0555 lea SR2ACIA,a1 *Serial-2 ACIA address to a1556 lea sr2dflt,a2 *Serial-2 dflt table addr to a2557 bsr.w aciainit *Go initialize the port558 * 513 514 move.l #nullfpu,0x0068 | Set FPU interrupt vector 515 move.l #api_int,0x006C | Set analog trap vector 516 move.l #timeint,0x0070 | Set timer trap vector 517 518 move.l #_hdvini,hdv_init | Set disk init vector 519 move.l #getbpb,hdv_bpb | Set get BPB vector 520 move.l #rwabs,hdv_rw | Set disk I/O vector 521 move.l #bootload,hdv_boot | Setup boot load vector 522 move.l #mediach,hdv_mchg | Setup media change vector 523 524 move.w #0xFFFF,fverify | Set read after write flag 525 move.w #FL_SKR,seekrate | Set default seek rate 526 move.w #0xFFFF,booted | Say we're not booted yet 527 move.l #buffer,dskbufp | Setup default disk buffer 528 529 .page 530 531 move.b #7,PSG_WL | Select PSG R7 532 move.b #0x80,PSG_WD | Write 0x80 (port B = output) 533 move.b #15,PSG_WL | Select PSG R15 534 move.b #0x00,PSG_WD | Write 0x00 (sync enable) 535 536 move.b #0x00,TIME_T1H | Setup timer 1 (PLL) 537 move.b #0x1F,TIME_T1L | ... for divide by 64 538 move.b #0x0C,TIME_T2H | Setup timer 2 (FC) 539 move.b #0x7F,TIME_T2L | ... for divide by 3200 540 move.b #0x03,TIME_T3H | Setup timer 3 (RTC) 541 move.b #0x20,TIME_T3L | ... for 1Ms interval 542 move.b #0x42,TIME_CRX | Setup CR3 543 move.b #0x41,TIME_CR2 | Setup CR2 544 move.b #0x81,TIME_CRX | Setup CR1 545 move.b #0x80,TIME_CRX | Start the timers 546 547 .endc 548 549 lea sr1iorec,a0 | Serial-1 iorec address to a0 550 lea SR1ACIA,a1 | Serial-1 ACIA address to a1 551 lea sr1dflt,a2 | Serial-1 dflt table addr to a2 552 bsr.w aciainit | Go initialize the port 553 554 lea sr2iorec,a0 | Serial-2 iorec address to a0 555 lea SR2ACIA,a1 | Serial-2 ACIA address to a1 556 lea sr2dflt,a2 | Serial-2 dflt table addr to a2 557 bsr.w aciainit | Go initialize the port 558 559 559 .ifne BUCHLA 560 * 561 lea mc1iorec,a0 *MIDI-1 iorec address to a0562 lea MC1ACIA,a1 *MIDI-1 ACIA address to a1563 lea mc1dflt,a2 *MIDI-1 dflt table addr to a2564 bsr.w aciainit *Go initialize the port565 * 566 lea mc2iorec,a0 *MIDI-2 iorec address to a0567 lea MC2ACIA,a1 *MIDI-2 ACIA address to a1568 lea mc2dflt,a2 *MIDI-2 dflt table addr to a2569 bsr.w aciainit *Go initialize the port570 * 571 .page 572 * 573 lea VSDDINIT,a1 *Setup to load VSDD regs574 lea vsddtab,a0 *... from vsddtab575 move.w #15,d0 *... all 16 registers576 * 577 vsddinit: move.w (a0)+,(a1)+ *Load the VSDD registers560 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 577 vsddinit: move.w (a0)+,(a1)+ | Load the VSDD registers 578 578 btst.l #0,d0 579 579 btst.l #0,d0 580 580 btst.l #0,d0 581 581 dbf d0,vsddinit 582 * 583 move.w vsddit02,VSDDINIT *Enable the video584 * 585 move.l #api_fum,api_fi *Clear analog processor fifo586 move.l #api_fum,api_fo *...587 * 588 move.w #23,d0 *Setup to clear key LEDs589 move.b # $80,d1 *...590 * 591 ledclear: move.b d1,LEDS *Clear a LED592 addq.b #1,d1 *Increment LED number593 dbra d0,ledclear *Loop until all are done594 * 595 move.w #7,d0 *Setup to clear pot LEDs596 move.b # $18,d1 *...597 * 598 ledclr2: move.b d1,LEDS *Clear a LED599 addq.b #1,d1 *Increment LED number600 dbra d0,ledclr2 *Loop until all are done601 * 602 clr.w fc_sw *Stop the frame clock603 clr.l fc_val *... and reset it604 * 605 .page 606 * 607 lea FPUBASE+FPU_CTL,a0 *Point at FPU master level608 move.w # $0000,$08(a0) *Set CV1 to 0609 addq.w #1,d0 *Delay610 addq.w #1,d0 *...611 move.w # $0000,$0A(a0) *Set SF1 to 0612 addq.w #1,d0 *Delay613 addq.w #1,d0 *...614 move.w # $0000,$0C(a0) *Set CV2 to 0615 addq.w #1,d0 *Delay616 addq.w #1,d0 *...617 move.w # $0000,$0E(a0) *Set SF2 to 0618 addq.w #1,d0 *Delay619 addq.w #1,d0 *...620 move.w # $0000,$10(a0) *Set CV3 to 0621 addq.w #1,d0 *Delay622 addq.w #1,d0 *...623 move.w # $0000,$12(a0) *Set SF3 to 0624 addq.w #1,d0 *Delay625 addq.w #1,d0 *...626 move.w # $8300,$02(a0) *Set new value '10' to -10.00627 addq.w #1,d0 *Delay628 addq.w #1,d0 *...629 move.w # $8300,$1C(a0) *Set new value '01' to -10.00630 addq.w #1,d0 *Delay631 addq.w #1,d0 *...632 move.w # $0001,$16(a0) *Set exponent for shortest time633 addq.w #1,d0 *Delay634 addq.w #1,d0 *...635 move.w # $FFF0,$14(a0) *Set mantissa for shortest time636 addq.w #1,d0 *Delay637 addq.w #1,d0 *...638 move.w # $0005,$00(a0) *Send control word to FPU639 * 640 .endc 641 * 642 .page 643 * 644 move.w #INITIPL,sr *Enable interrupts645 lea basepage,a1 *Pass start_ a pseudo base page646 move.l #_errno,p_bbase(a1) *...647 clr.l p_blen(a1) *...648 move.l a1,-(a7) *...649 jsr start_ *Go start ROMP (we assume ...)650 * 651 jmp biosinit *Just in case we return ...652 * 653 .page 654 * 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 591 ledclear: 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 598 ledclr2: move.b d1,LEDS | Clear a LED 599 addq.b #1,d1 | Increment LED number 600 dbra d0,ledclr2 | Loop until all are done 601 602 clr.w fc_sw | Stop the frame clock 603 clr.l fc_val | ... and reset it 604 605 .page 606 607 lea FPUBASE+FPU_CTL,a0 | Point at FPU master level 608 move.w #0x0000,0x08(a0) | Set CV1 to 0 609 addq.w #1,d0 | Delay 610 addq.w #1,d0 | ... 611 move.w #0x0000,0x0A(a0) | Set SF1 to 0 612 addq.w #1,d0 | Delay 613 addq.w #1,d0 | ... 614 move.w #0x0000,0x0C(a0) | Set CV2 to 0 615 addq.w #1,d0 | Delay 616 addq.w #1,d0 | ... 617 move.w #0x0000,0x0E(a0) | Set SF2 to 0 618 addq.w #1,d0 | Delay 619 addq.w #1,d0 | ... 620 move.w #0x0000,0x10(a0) | Set CV3 to 0 621 addq.w #1,d0 | Delay 622 addq.w #1,d0 | ... 623 move.w #0x0000,0x12(a0) | Set SF3 to 0 624 addq.w #1,d0 | Delay 625 addq.w #1,d0 | ... 626 move.w #0x8300,0x02(a0) | Set new value '10' to -10.00 627 addq.w #1,d0 | Delay 628 addq.w #1,d0 | ... 629 move.w #0x8300,0x1C(a0) | Set new value '01' to -10.00 630 addq.w #1,d0 | Delay 631 addq.w #1,d0 | ... 632 move.w #0x0001,0x16(a0) | Set exponent for shortest time 633 addq.w #1,d0 | Delay 634 addq.w #1,d0 | ... 635 move.w #0xFFF0,0x14(a0) | Set mantissa for shortest time 636 addq.w #1,d0 | Delay 637 addq.w #1,d0 | ... 638 move.w #0x0005,0x00(a0) | Send control word to FPU 639 640 .endc 641 642 .page 643 644 move.w #INITIPL,sr | Enable interrupts 645 lea basepage,a1 | Pass start_ a pseudo base page 646 move.l #_errno,p_bbase(a1) | ... 647 clr.l p_blen(a1) | ... 648 move.l a1,-(a7) | ... 649 jsr start_ | Go start ROMP (we assume ...) 650 651 jmp biosinit | Just in case we return ... 652 653 .page 654 655 655 .ifne BUCHLA 656 * 657 *nullfpu -- Null FPU trap handler658 *------- ---------------------659 nullfpu: movem.l d0-d0/a0-a0,-(a7) *Save registers660 movea.l #FPUBASE,a0 *Setup FPU base address in a0661 move.w FPU_IN(a0),d0 *Read FPU interrupt port662 andi.l # $000000FF,d0 *Mask for voice & parameter663 lsl.l #5,d0 *Shift for word offset664 addi.l #FPU_CTL,d0 *Add FPU control offset665 move.w #FPU_RST,0(a0,d0.L) *Reset the function666 clr.w FPU_CLR(a0) *Clear the interrupt667 movem.l (a7)+,d0-d0/a0-a0 *Restore registers668 rte *Return to interrupted code669 * 670 .endc 671 * 672 .page 673 * 674 *hardhlt -- Bus error trap handler675 *------- ----------------------676 hardhlt: stop # $2700 *stop dead -- system is AFU677 bra hardhlt *...678 * 679 *badtrap -- Bad trap handler680 *------- ----------------681 badtrap: move.w (a7)+,_crshsr *Get crash SR682 move.l (a7)+,_crshpc *Get crash PC683 move.l a7,_crshsp *Get crash SP684 bsr badtr1 *Get TRAP PC with vector number656 657 | nullfpu -- Null FPU trap handler 658 | ------- --------------------- 659 nullfpu: movem.l d0-d0/a0-a0,-(a7) | Save registers 660 movea.l #FPUBASE,a0 | Setup FPU base address in a0 661 move.w FPU_IN(a0),d0 | Read FPU interrupt port 662 andi.l #0x000000FF,d0 | Mask for voice & parameter 663 lsl.l #5,d0 | Shift for word offset 664 addi.l #FPU_CTL,d0 | Add FPU control offset 665 move.w #FPU_RST,0(a0,d0.L) | Reset the function 666 clr.w FPU_CLR(a0) | Clear the interrupt 667 movem.l (a7)+,d0-d0/a0-a0 | Restore registers 668 rte | Return to interrupted code 669 670 .endc 671 672 .page 673 674 | hardhlt -- Bus error trap handler 675 | ------- ---------------------- 676 hardhlt: stop #0x2700 | stop dead -- system is AFU 677 bra hardhlt | ... 678 679 | badtrap -- Bad trap handler 680 | ------- ---------------- 681 badtrap: move.w (a7)+,_crshsr | Get crash SR 682 move.l (a7)+,_crshpc | Get crash PC 683 move.l a7,_crshsp | Get crash SP 684 bsr badtr1 | Get TRAP PC with vector number 685 685 nop 686 * 687 badtr1: move.l (a7)+,_crshvc *Save for analysis of vector #688 movem.l d0-d7/a0-a7,_crshrg *Save crash registers689 move.l usp,a0 *Preserve crash USP690 move.l a0,_crshus *...691 move.l a7,d0 *Get SP692 andi.l # $FFFFFFFE,d0 *... make sure it's even693 movea.l d0,a1 *...694 move.w #15,d0 *Save top 16 words695 lea _crshst,a0 *... of crash stack in _crshst696 * 697 badtr2: move.w (a1)+,(a0)+ *Save a stack value698 dbf d0,badtr2 *Loop until all are saved699 * 700 clr.l d0 *Get TRAP number701 move.b _crshvc,d0 *... as LS byte of d0702 move.l _crshpc,a0 *Save crash PC in a0703 move.w # $FFFF,_wzcrsh *Indicate we crashed704 move.l #rsarea,savptr *Restore system save pointer705 move.l #SSTACK,a7 *Reset the stack pointer706 move.l #RSMAGIC,_rsflag *... and the stack sentinel707 trap #15 *TRAP to ROMP708 * 709 jmp biosinit *Recover with a cold start710 * 711 .page 712 * 686 687 badtr1: move.l (a7)+,_crshvc | Save for analysis of vector # 688 movem.l d0-d7/a0-a7,_crshrg | Save crash registers 689 move.l usp,a0 | Preserve crash USP 690 move.l a0,_crshus | ... 691 move.l a7,d0 | Get SP 692 andi.l #0xFFFFFFFE,d0 | ... make sure it's even 693 movea.l d0,a1 | ... 694 move.w #15,d0 | Save top 16 words 695 lea _crshst,a0 | ... of crash stack in _crshst 696 697 badtr2: move.w (a1)+,(a0)+ | Save a stack value 698 dbf d0,badtr2 | Loop until all are saved 699 700 clr.l d0 | Get TRAP number 701 move.b _crshvc,d0 | ... as LS byte of d0 702 move.l _crshpc,a0 | Save crash PC in a0 703 move.w #0xFFFF,_wzcrsh | Indicate we crashed 704 move.l #rsarea,savptr | Restore system save pointer 705 move.l #SSTACK,a7 | Reset the stack pointer 706 move.l #RSMAGIC,_rsflag | ... and the stack sentinel 707 trap #15 | TRAP to ROMP 708 709 jmp biosinit | Recover with a cold start 710 711 .page 712 713 713 .ifne BUCHLA 714 * 715 *timeint -- Timer interrupt handler716 *------- -----------------------717 timeint: movem.l d0-d7/a0-a6,-(a7) *Save registers718 move.b TIME_CR2,d0 *Get timer interrupt status719 btst.l #2,d0 *Check timer 3 status720 beq tmi02 *Jump if not active721 * 722 move.b TIME_T3H,d1 *Read timer 1 count723 lsl.l #8,d1 *...724 move.b TIME_T3L,d1 *...725 move.w d1,t3count *... and save it726 * 727 addq.l #1,_hz_1k *Update 1ms clock (1 KHz)728 * 729 move.w tdiv1,d1 *Update divider730 addq.w #1,d1 *...731 move.w d1,tdiv1 *...732 * 733 cmpi.w #5,d1 *Do we need to update _hz_200 ?734 blt tmi02 *Jump if not735 * 736 addq.l #1,_hz_200 *Update 5ms clock (200 Hz)737 * 738 move.w tdiv2,d1 *Update divider739 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 not744 * 745 addq.l #1,frclock *Update 20 Ms clock (50 Hz)746 tst.w flock *See if floppy is active747 bne tmi00 *Don't call flopvbl if so748 * 749 bsr flopvbl *Check on the floppy750 * 751 tmi00: move.w #0,tdiv2 *Reset tdiv2752 * 753 tmi01: move.w #0,tdiv1 *Reset tdiv1754 * 755 .page 756 * 757 tmi02: btst.l #0,d0 *Check timer 1 int758 beq tmi03 *Jump if not set759 * 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 count764 * 765 tmi03: btst.l #1,d0 *Check for timer 2 int.766 beq tmi04 *Jump if not set767 * 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 count772 * 773 tst.w fc_sw *Should we update the frame ?774 beq tmi04 *Jump if not775 * 776 bmi tmi05 *Jump if we count down777 * 778 move.l fc_val,d0 *Get the frame count779 cmp.l #FCMAX,d0 *See it we've topped out780 bge tmi06 *Jump if limit was hit781 * 782 addq.l #1,d0 *Count up 1 frame783 move.l d0,fc_val *Store updated frame count784 bra tmi04 *Done785 * 786 tmi06: move.l #FCMAX,fc_val *Force hard limit, just in case787 bra tmi04 *Done788 * 789 tmi05: move.l fc_val,d0 *Get the frame count790 beq tmi04 *Done if already zero791 * 792 subq.l #1,d0 *Count down 1 frame793 move.l d0,fc_val *Store udpated frame count794 * 795 movea.l timevec,a0 *Do RTC vector796 move.w #1,-(a7) *... pass 1 msec on stack797 jsr (a0) *...798 addq.l #4,a7 *...799 * 800 tmi04: movem.l (a7)+,d0-d7/a0-a6 *Restore registers801 rte *Return to interrupted code802 * 803 .endc 804 * 805 .page 806 * 807 *trap14 -- Extended BIOS entry point808 *------ -------------------------809 trap14: lea t14tab,a0 *Setup trap 14 table address810 bra trapent *Go process trap811 * 812 *trap13 -- Main BIOS entry point813 *------ ---------------------814 trap13: lea t13tab,a0 *Setup trap 13 table address815 * 816 trapent: move.l savptr,a1 *Get save area pointer817 move.w (a7)+,d0 *Status register to D0818 move.w d0,-(a1) *Save in save area819 move.l (a7)+,-(a1) *Stash PC in save area820 movem.l d3-d7/a3-a7,-(a1) *Save parameter register821 move.l a1,savptr *Update save pointer822 btst #13,d0 *Were we in sup. mode ?823 bne trwzsup *Jump if so824 * 825 move.l usp,a7 *Move user sp to stack ptr.826 * 827 trwzsup: move.w (a7)+,d0 *Get function number from stack828 cmp.w (a0)+,d0 *Check against limit829 bge trpexit *Jump if it's invalid830 * 831 lsl.w #2,d0 *Multiply by 4 for use as index832 move.l 0(a0,d0),d0 *Get routine address833 move.l d0,a0 *... into a0834 bpl trpnind *Jump if it's indirect835 * 836 move.l (a0),a0 *Use indirect value837 * 838 trpnind: sub.l a5,a5 *Clear a5839 jsr (a0) *Execute the routine840 * 841 trpexit: move.l savptr,a1 *Get SAVPTR into a1842 movem.l (a1)+,d3-d7/a3-a7 *Restore registers843 move.l (a1)+,-(a7) *Push return onto stack844 move.w (a1)+,-(a7) *Push status onto stack845 move.l a1,savptr *Update SAVPTR846 * 847 *nullrte -- null rte848 *------- --------849 nullrte: rte *Return to interrupted code850 * 851 *nullrts -- null return852 *------- -----------853 nullrts: rts *Just return to the caller854 * 855 .page 856 * 857 *bconstat -- Get character device input status858 *-------- ---------------------------------859 bconstat: lea cdt01,a0 *Point at status table860 bra condisp *Jump to dispatcher861 * 862 *bconin -- Get input from character device863 *------ -------------------------------864 bconin: lea cdt02,a0 *Point at input table865 bra condisp *Jump to dispatcher866 * 867 *bconout -- Output to character device868 *------- --------------------------869 bconout: lea cdt03,a0 *Point at output table870 bra condisp *Jump to dispatcher871 * 872 *bcostat -- Get character device output status873 *------- ----------------------------------874 bcostat: lea cdt04,a0 *Point at status table875 * 876 *condisp -- Character device function dispatcher877 *------- ------------------------------------878 condisp: move.w 4(a7),d0 *Get device number879 lsl.w #2,d0 *... times 4 for pointer880 move.l 0(a0,d0),a0 *Get routine address881 jmp (a0) *Jump to it882 * 883 .page 884 * 885 *sr1ist -- Check CON (Serial-1) input buffer status886 *------ ----------------------------------------887 sr1ist: lea sr1iorec,a0 *Address of iorec to a0888 lea SR1ACIA,a1 *Address of ACIA to a1889 bra chkist *Go check buffer status890 * 891 *sr2ist -- Check AUX (Serial-2) input buffer status892 *------ ----------------------------------------893 sr2ist: lea sr2iorec,a0 *Address of iorec to a0894 lea SR2ACIA,a1 *Address of ACIA to a1895 * 714 715 | timeint -- Timer interrupt handler 716 | ------- ----------------------- 717 timeint: movem.l d0-d7/a0-a6,-(a7) | Save registers 718 move.b TIME_CR2,d0 | Get timer interrupt status 719 btst.l #2,d0 | Check timer 3 status 720 beq tmi02 | Jump if not active 721 722 move.b TIME_T3H,d1 | Read timer 1 count 723 lsl.l #8,d1 | ... 724 move.b TIME_T3L,d1 | ... 725 move.w d1,t3count | ... and save it 726 727 addq.l #1,_hz_1k | Update 1ms clock (1 KHz) 728 729 move.w tdiv1,d1 | Update divider 730 addq.w #1,d1 | ... 731 move.w d1,tdiv1 | ... 732 733 cmpi.w #5,d1 | Do we need to update _hz_200 ? 734 blt tmi02 | Jump if not 735 736 addq.l #1,_hz_200 | Update 5ms clock (200 Hz) 737 738 move.w tdiv2,d1 | Update divider 739 addq.w #1,d1 | ... 740 move.w d1,tdiv2 | ... 741 742 cmpi.w #4,d1 | Do we need to update frclock ? 743 blt tmi01 | Jump if not 744 745 addq.l #1,frclock | Update 20 Ms clock (50 Hz) 746 tst.w flock | See if floppy is active 747 bne tmi00 | Don't call flopvbl if so 748 749 bsr flopvbl | Check on the floppy 750 751 tmi00: move.w #0,tdiv2 | Reset tdiv2 752 753 tmi01: move.w #0,tdiv1 | Reset tdiv1 754 755 .page 756 757 tmi02: 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 765 tmi03: 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 786 tmi06: move.l #FCMAX,fc_val | Force hard limit, just in case 787 bra tmi04 | Done 788 789 tmi05: 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 800 tmi04: movem.l (a7)+,d0-d7/a0-a6 | Restore registers 801 rte | Return to interrupted code 802 803 .endc 804 805 .page 806 807 | trap14 -- Extended BIOS entry point 808 | ------ ------------------------- 809 trap14: lea t14tab,a0 | Setup trap 14 table address 810 bra trapent | Go process trap 811 812 | trap13 -- Main BIOS entry point 813 | ------ --------------------- 814 trap13: lea t13tab,a0 | Setup trap 13 table address 815 816 trapent: 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 827 trwzsup: 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 838 trpnind: sub.l a5,a5 | Clear a5 839 jsr (a0) | Execute the routine 840 841 trpexit: 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 | ------- -------- 849 nullrte: rte | Return to interrupted code 850 851 | nullrts -- null return 852 | ------- ----------- 853 nullrts: rts | Just return to the caller 854 855 .page 856 857 | bconstat -- Get character device input status 858 | -------- --------------------------------- 859 bconstat: lea cdt01,a0 | Point at status table 860 bra condisp | Jump to dispatcher 861 862 | bconin -- Get input from character device 863 | ------ ------------------------------- 864 bconin: lea cdt02,a0 | Point at input table 865 bra condisp | Jump to dispatcher 866 867 | bconout -- Output to character device 868 | ------- -------------------------- 869 bconout: lea cdt03,a0 | Point at output table 870 bra condisp | Jump to dispatcher 871 872 | bcostat -- Get character device output status 873 | ------- ---------------------------------- 874 bcostat: lea cdt04,a0 | Point at status table 875 876 | condisp -- Character device function dispatcher 877 | ------- ------------------------------------ 878 condisp: 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 | ------ ---------------------------------------- 887 sr1ist: 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 | ------ ---------------------------------------- 893 sr2ist: lea sr2iorec,a0 | Address of iorec to a0 894 lea SR2ACIA,a1 | Address of ACIA to a1 895 896 896 .ifne BUCHLA 897 * 898 bra chkist *Go check buffer status899 * 900 *mc1ist -- Check MC1 (MIDI-1) input buffer status901 *------ --------------------------------------902 mc1ist: lea mc1iorec,a0 *Address of iorec to a0903 lea MC1ACIA,a1 *Address of ACIA to a1904 bra chkist *Go check buffer status905 * 906 *mc2ist -- Check MC2 (MIDI-2) input buffer status907 *------ --------------------------------------908 mc2ist: lea mc2iorec,a0 *Address of iorec to a0909 lea MC2ACIA,a1 *Address of ACIA to a1910 * 911 .endc 912 * 913 *chkist -- Check input buffer status914 *------ -------------------------915 chkist: moveq.l #-1,d0 *Default to "Input available"916 lea ibufhd(a0),a2 *Head index to a2917 lea ibuftl(a0),a3 *Tail index to a3918 cmpm.w (a3)+,(a2)+ *Buffer clear ?919 bne chkist1 *Jump if not920 * 921 moveq.l #0,d0 *Set to "Buffer empty"922 * 923 chkist1: rts *Return to caller924 * 925 .page 926 * 927 *sr1ost -- Check CON (Serial-1) output buffer status928 *------ -----------------------------------------929 sr1ost: lea sr1iorec,a0 *Address of iorec to a0930 bra chkost *Go check buffer status931 * 932 *sr2ost -- Check AUX (Serial-2) output buffer status933 *------ -----------------------------------------934 sr2ost: lea sr2iorec,a0 *Address of iorec to a0935 * 897 898 bra chkist | Go check buffer status 899 900 | mc1ist -- Check MC1 (MIDI-1) input buffer status 901 | ------ -------------------------------------- 902 mc1ist: 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 | ------ -------------------------------------- 908 mc2ist: lea mc2iorec,a0 | Address of iorec to a0 909 lea MC2ACIA,a1 | Address of ACIA to a1 910 911 .endc 912 913 | chkist -- Check input buffer status 914 | ------ ------------------------- 915 chkist: 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 923 chkist1: rts | Return to caller 924 925 .page 926 927 | sr1ost -- Check CON (Serial-1) output buffer status 928 | ------ ----------------------------------------- 929 sr1ost: 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 | ------ ----------------------------------------- 934 sr2ost: lea sr2iorec,a0 | Address of iorec to a0 935 936 936 .ifne BUCHLA 937 * 938 bra chkost *Go check buffer status939 * 940 *mc1ost -- Check MC1 (MIDI-1) output buffer status941 *------ ---------------------------------------942 mc1ost: lea mc1iorec,a0 *Address of iorec to a0943 bra chkost *Go check buffer status944 * 945 *mc2ost -- Check MC2 (MIDI-2) output buffer status946 *------ ---------------------------------------947 mc2ost: lea mc2iorec,a0 *Address of iorec to a0948 * 949 .endc 950 * 951 *chkost -- Check output buffer status952 *------ --------------------------953 chkost: moveq.l #-1,d0 *Default to "Output OK"954 move.w obuftl(a0),d2 *Tail index to d2955 bsr wrapout *Test for pointer wraparound956 cmp.w obufhd(a0),d2 *Compare with head index957 bne chkost1 *Jump if not equal958 * 959 moveq.l #0,d0 *Set to "Buffer full"960 * 961 chkost1: rts *Return to caller962 * 963 .page 964 * 965 *wrapin -- Check input pointer for wraparound966 *------ ----------------------------------967 wrapin: add.w #1,d1 *Head index +1968 cmp.w ibufsize(a0),d1 *= buffer size ?969 bcs wrapin1 *Jump if not970 * 971 moveq.l #0,d1 *Wraparound972 * 973 wrapin1: rts *Return to caller974 * 975 *wrapout -- Check output pointer for wraparound976 *------- -----------------------------------977 wrapout: addq.w #1,d2 *Tail index +1978 cmp.w obufsize(a0),d2 *= buffer size ?979 bcs wrapout1 *Jump if not980 * 981 moveq.l #0,d2 *Wrap around if so982 * 983 wrapout1: rts *Return to caller984 * 985 .page 986 * 987 *sr1inp -- Get input from Serial-1 (wait on busy)988 *------ ---------------------------------------989 sr1inp: lea sr1iorec,a0 *Serial-1 iorec address990 lea SR1ACIA,a1 *Serial-1 ACIA base991 bra serinp *Go get a byte992 * 993 *sr2inp -- Get input from Serial-2 (wait on busy)994 *------ ---------------------------------------995 sr2inp: lea sr2iorec,a0 *Serial-2 iorec address996 lea SR2ACIA,a1 *Serial-2 ACIA base997 * 998 *serinp -- Get a byte from a serial port (with handshaking)999 *------ -------------------------------------------------1000 serinp: bsr chkist *Check input status1001 tst.w d0 *Character ready ?1002 beq serinp *Loop until one is ...1003 * 1004 bsr getser *Get a byte from the buffer1005 and.w # $FFFF,d0 *Isolate LS bits 7..01006 rts *Return to caller1007 * 1008 .page 1009 * 937 938 bra chkost | Go check buffer status 939 940 | mc1ost -- Check MC1 (MIDI-1) output buffer status 941 | ------ --------------------------------------- 942 mc1ost: 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 | ------ --------------------------------------- 947 mc2ost: lea mc2iorec,a0 | Address of iorec to a0 948 949 .endc 950 951 | chkost -- Check output buffer status 952 | ------ -------------------------- 953 chkost: 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 961 chkost1: rts | Return to caller 962 963 .page 964 965 | wrapin -- Check input pointer for wraparound 966 | ------ ---------------------------------- 967 wrapin: 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 973 wrapin1: rts | Return to caller 974 975 | wrapout -- Check output pointer for wraparound 976 | ------- ----------------------------------- 977 wrapout: 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 983 wrapout1: rts | Return to caller 984 985 .page 986 987 | sr1inp -- Get input from Serial-1 (wait on busy) 988 | ------ --------------------------------------- 989 sr1inp: 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 | ------ --------------------------------------- 995 sr2inp: 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 | ------ ------------------------------------------------- 1000 serinp: bsr chkist | Check input status 1001 tst.w d0 | Character ready ? 1002 beq serinp | Loop until one is ... 1003 1004 bsr getser | Get a byte from the buffer 1005 and.w #0xFFFF,d0 | Isolate LS bits 7..0 1006 rts | Return to caller 1007 1008 .page 1009 1010 1010 .ifne BUCHLA 1011 * 1012 *mc1inp -- Get input from MIDI-1 (wait on busy)1013 *------ -------------------------------------1014 mc1inp: lea mc1iorec,a0 *MIDI-1 iorec address1015 lea MC1ACIA,a1 *MIDI-1 ACIA base1016 bra midinp *Go get a byte1017 * 1018 *mc2inp -- Get input from MIDI-2 (wait on busy)1019 *------ -------------------------------------1020 mc2inp: lea mc2iorec,a0 *MIDI-2 iorec address1021 lea MC2ACIA,a1 *MIDI-2 ACIA base1022 * 1023 *midinp -- Get input from a MIDI port (no handshaking)1024 *------ --------------------------------------------1025 midinp: bsr chkist *Check input status1026 tst.w d0 *Character ready ?1027 beq midinp *Loop until one is ...1028 * 1029 move.w sr,-(a7) *Save status register1030 ori.w #IPL7,sr *Set IPL = 7 (disable ints)1031 move.w ibufhd(a0),d1 *Head index to d11032 cmp.w ibuftl(a0),d1 *Compare to tail index1033 beq midin_1 *Jump if (somehow) empty1034 * 1035 addq.w #1,d1 *Increment head index1036 cmp.w ibufsize(a0),d1 *Did pointer wrap around ?1037 bcs midin_2 *Jump if not1038 * 1039 moveq.l #0,d1 *Wraparound1040 * 1041 midin_2: move.l ibuf(a0),a2 *Get buffer base address in a21042 moveq.l #0,d0 *Clear MS bits of d01043 move.b 0(a2,d1),d0 *Get character from buffer1044 move.w d1,ibufhd(a0) *Update buffer head index1045 * 1046 midin_1: move.w (a7)+,sr *Restore status1047 rts *Return to caller1048 * 1049 .endc 1050 * 1051 .page 1052 * 1053 *getser -- Get a byte from a serial port buffer (with handshaking)1054 *------ --------------------------------------------------------1055 getser: move.w sr,-(a7) *Save status register1056 ori.w #IPL7,sr *Set IPL = 7 (disable ints)1057 move.w ibufhd(a0),d1 *Get input buffer head index1058 cmp.w ibuftl(a0),d1 *Compare tail index1059 beq rs_mt *Jump if buffer empty1060 * 1061 bsr wrapin *Adjust pointer for wraparound1062 move.l ibuf(a0),a2 *Get buffer address1063 moveq.l #0,d0 *Clear out MS bits of d01064 move.b 0(a2,d1),d0 *Get character from buffer1065 move.w d1,ibufhd(a0) *Update head index1066 move.w (a7)+,sr *Restore status1067 andi # $FFFE,sr *Clear carry = OK1068 bra rs_xnf *Go do XON/XOFF check1069 * 1070 rs_mt: move.w (a7)+,sr *Restore status1071 ori # $0001,sr *Set carry = no character there1072 * 1073 rs_xnf: btst #0,linedisc(a0) *Check for XON/XOFF mode1074 beq rs_exit *Jump if not enabled1075 * 1076 tst.b flagxon(a0) *XON active ?1077 beq rs_exit *Jump if not1078 * 1079 bsr rsilen *Get length of buffer used1080 cmp.w ibuflow(a0),d2 *At low water mark ?1081 bne rs_exit *Jump if not1082 * 1083 move.b # $11,d1 *Send an XON1084 bsr serput *...1085 clr.b flagxon(a0) *Clear XON flag1086 * 1087 rs_exit: rts *Return to caller1088 * 1089 .page 1090 * 1091 *sr1out -- Output to serial-11092 *------ ------------------1093 sr1out: lea sr1iorec,a0 *Serial-1 iorec address to a01094 lea SR1ACIA,a1 *Serial-1 ACIA address to a11095 move.w 6(a7),d1 *Get data byte from stack1096 bsr serput *Attempt to output1097 bcs sr1out *Try until it works ...1098 * 1099 rts *Return to caller1100 * 1101 *sr2out -- Output to Serial-21102 *------ ------------------1103 sr2out: lea sr2iorec,a0 *Serial-2 iorec address to a01104 lea SR2ACIA,a1 *Serial-2 ACIA address to a11105 move.w 6(a7),d1 *Get data byte from stack1106 bsr serput *Attempt to output1107 bcs sr2out *Try until it works ...1108 * 1109 rts *Return to caller1110 * 1011 1012 | mc1inp -- Get input from MIDI-1 (wait on busy) 1013 | ------ ------------------------------------- 1014 mc1inp: 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 | ------ ------------------------------------- 1020 mc2inp: 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 | ------ -------------------------------------------- 1025 midinp: 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 1041 midin_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 1046 midin_1: move.w (a7)+,sr | Restore status 1047 rts | Return to caller 1048 1049 .endc 1050 1051 .page 1052 1053 | getser -- Get a byte from a serial port buffer (with handshaking) 1054 | ------ -------------------------------------------------------- 1055 getser: 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 1070 rs_mt: move.w (a7)+,sr | Restore status 1071 ori #0x0001,sr | Set carry = no character there 1072 1073 rs_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 1087 rs_exit: rts | Return to caller 1088 1089 .page 1090 1091 | sr1out -- Output to serial-1 1092 | ------ ------------------ 1093 sr1out: 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 | ------ ------------------ 1103 sr2out: lea sr2iorec,a0 | Serial-2 iorec address to a0 1104 lea SR2ACIA,a1 | Serial-2 ACIA address to a1 1105 move.w 6(a7),d1 | Get data byte from stack 1106 bsr serput | Attempt to output 1107 bcs sr2out | Try until it works ... 1108 1109 rts | Return to caller 1110 1111 1111 .ifne BUCHLA 1112 * 1113 *mc1out -- Output to MIDI-11114 *------ ----------------1115 mc1out: lea mc1iorec,a0 *MIDI-1 iorec address to a01116 lea MC1ACIA,a1 *MIDI-1 ACIA address to a11117 move.w 6(a7),d1 *Get data byte from stack1118 bsr midput *Attempt to output1119 bcs mc1out *Try until it works ...1120 * 1121 rts *Return to caller1122 * 1123 *mc2out -- Output to MIDI-21124 *------ ----------------1125 mc2out: lea mc2iorec,a0 *MIDI-2 iorec address to a01126 lea MC2ACIA,a1 *MIDI-2 ACIA address to a11127 move.w 6(a7),d1 *Get data byte from stack1128 bsr midput *Attempt to output1129 bcs mc2out *Try until it works ...1130 * 1131 rts *Return to caller1132 * 1133 .endc 1134 * 1135 .page 1136 * 1137 *serput -- Output a character to a serial port1138 *------ -----------------------------------1139 serput: move.w sr,-(a7) *Save status register1140 ori.w #IPL7,sr *Set IPL = 7 (disable ints)1141 move.b ACIA_ISR(a1),isr(a0) *Get ACIA isr1142 move.b ACIA_CSR(a1),csr(a0) *Get ACIA csr1143 btst #0,linedisc(a0) *XON/XOFF mode ?1144 beq serpt_1 *Jump if not1145 * 1146 tst.b flagxoff(a0) *XON active ?1147 bne serpt_2 *Jump if so1148 * 1149 serpt_1: btst.b #6,isr(a0) *Is ACIA still sending ?1150 beq serpt_2 *Jump if so1151 * 1152 move.w obufhd(a0),d2 *Head index to d21153 cmp.w obuftl(a0),d2 *Compare to tail index1154 bne serpt_2 *Jump if buffer not empty1155 * 1156 move.b d1,ACIA_TDR(a1) *Give byte to ACIA to send1157 bra serpt_3 *Go deal with RTS/CTS if needed1158 * 1159 serpt_2: move.w obuftl(a0),d2 *Tail index to d21160 bsr wrapout *Adjust for wraparound1161 cmp.w obufhd(a0),d2 *Compare to head index1162 beq serpt_4 *Jump if buffer full1163 * 1164 move.l obuf(a0),a2 *Get buffer base address in a21165 move.b d1,0(a2,d2) *Put character in buffer1166 move.w d2,obuftl(a0) *Update buffer tail index1167 * 1168 serpt_3: bsr serchk *Check status on our way out1169 bsr rtschk *Handle RTS protocol1170 move.w (a7)+,sr *Restore status register1171 andi # $FFFE,sr *Clear carry flag = OK1172 rts *Return to caller1173 * 1174 serpt_4: bsr serchk *Check status on our way out1175 bsr rtschk *Handle RTS protocol1176 move.w (a7)+,sr *Restore status register1177 ori # $0001,sr *Set carry flag = buffer full1178 rts *Return to caller1179 * 1180 .page 1181 * 1112 1113 | mc1out -- Output to MIDI-1 1114 | ------ ---------------- 1115 mc1out: 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 | ------ ---------------- 1125 mc2out: lea mc2iorec,a0 | MIDI-2 iorec address to a0 1126 lea MC2ACIA,a1 | MIDI-2 ACIA address to a1 1127 move.w 6(a7),d1 | Get data byte from stack 1128 bsr midput | Attempt to output 1129 bcs mc2out | Try until it works ... 1130 1131 rts | Return to caller 1132 1133 .endc 1134 1135 .page 1136 1137 | serput -- Output a character to a serial port 1138 | ------ ----------------------------------- 1139 serput: 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 1149 serpt_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 1159 serpt_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 1168 serpt_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 1174 serpt_4: bsr serchk | Check status on our way out 1175 bsr rtschk | Handle RTS protocol 1176 move.w (a7)+,sr | Restore status register 1177 ori #0x0001,sr | Set carry flag = buffer full 1178 rts | Return to caller 1179 1180 .page 1181 1182 1182 .ifne BUCHLA 1183 * 1184 *midput -- Output to MIDI1185 *------ --------------1186 midput: move.w sr,-(a7) *Save status register1187 ori.w #IPL7,sr *Set IPL = 7 (diable ints)1188 move.b ACIA_ISR(a1),isr(a0) *Get ACIA isr1189 move.b ACIA_CSR(a1),csr(a0) *Get ACIA csr1190 btst.b #6,isr(a0) *Is ACIA still sending ?1191 beq midpt_2 *Jump if so1192 * 1193 move.w obufhd(a0),d2 *Head index to d21194 cmp.w obuftl(a0),d2 *Compare to tail index1195 bne midpt_2 *Jump if buffer not empty1196 * 1197 move.b d1,ACIA_TDR(a1) *Give byte to ACIA to send1198 bra midpt_3 *Go set final status and exit1199 * 1200 midpt_2: move.w obuftl(a0),d2 *Tail index to d21201 bsr wrapout *Adjust for wraparound1202 cmp.w obufhd(a0),d2 *Compare to head index1203 beq midpt_4 *Jump if buffer full1204 * 1205 move.l obuf(a0),a2 *Get buffer base address in a21206 move.b d1,0(a2,d2) *Put character in buffer1207 move.w d2,obuftl(a0) *Update buffer tail index1208 * 1209 midpt_3: bsr midchk *Check status on our way out1210 move.w (a7)+,sr *Restore status register1211 andi # $FFFE,sr *Clear carry flag = OK1212 rts *Return to caller1213 * 1214 midpt_4: bsr midchk *Check status on our way out1215 move.w (a7)+,sr *Restore status register1216 ori # $0001,sr *Set carry flag = buffer full1217 rts *Return to caller1218 * 1219 .endc 1220 * 1221 .page 1222 * 1223 *rtschk -- Check RTS mode and turn on RTS if it's enabled1224 *------ ----------------------------------------------1225 rtschk: btst #1,linedisc(a0) *RTS/CTS mode set ?1226 beq rts_1 *Jump if not1227 * 1228 bsr rtson *Turn on RTS1229 * 1230 rts_1: rts *Return to caller1231 * 1232 *rsilen -- Get length of portion of input buffer that's been used so far1233 *------ -------------------------------------------------------------1234 rsilen: move.w ibuftl(a0),d2 *Tail index to d21235 move.w ibufhd(a0),d3 *Head index to d31236 cmp.w d3,d2 *Head > Tail ?1237 bhi rsi_1 *Jump if not1238 * 1239 add.w ibufsize(a0),d2 *Add buffer size to tail index1240 * 1241 rsi_1: sub.w d3,d2 *Length = (adjusted)Tail - Head1242 rts *Return to caller1243 * 1244 *rtson -- Turn on RTS line1245 *----- ----------------1246 rtson: move.b cfr1(a0),d0 *Pick up CFR1 image1247 bclr #0,d0 *Turn on RTS line (active low)1248 bset #7,d0 *Make sure MS bit is set1249 move.b d0,cfr1(a0) *Update CFR1 image1250 move.b d0,ACIA_CFR(a1) *Send CFR to hardware1251 rts *Return to caller1252 * 1253 *rtsoff -- Turn off RTS line1254 *------ -----------------1255 rtsoff: move.b cfr1(a0),d0 *Pick up CFR1 image1256 bset #0,d0 *Turn off RTS line (active low)1257 bset #7,d0 *Make sure MS bit is set1258 move.b d0,cfr1(a0) *Update CFR1 image1259 move.b d0,ACIA_CFR(a1) *Send CFR to hardware1183 1184 | midput -- Output to MIDI 1185 | ------ -------------- 1186 midput: 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 1200 midpt_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 1209 midpt_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 1214 midpt_4: bsr midchk | Check status on our way out 1215 move.w (a7)+,sr | Restore status register 1216 ori #0x0001,sr | Set carry flag = buffer full 1217 rts | Return to caller 1218 1219 .endc 1220 1221 .page 1222 1223 | rtschk -- Check RTS mode and turn on RTS if it's enabled 1224 | ------ ---------------------------------------------- 1225 rtschk: btst #1,linedisc(a0) | RTS/CTS mode set ? 1226 beq rts_1 | Jump if not 1227 1228 bsr rtson | Turn on RTS 1229 1230 rts_1: rts | Return to caller 1231 1232 | rsilen -- Get length of portion of input buffer that's been used so far 1233 | ------ ------------------------------------------------------------- 1234 rsilen: 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 1241 rsi_1: sub.w d3,d2 | Length = (adjusted)Tail - Head 1242 rts | Return to caller 1243 1244 | rtson -- Turn on RTS line 1245 | ----- ---------------- 1246 rtson: 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 | ------ ----------------- 1255 rtsoff: move.b cfr1(a0),d0 | Pick up CFR1 image 1256 bset #0,d0 | Turn off RTS line (active low) 1257 bset #7,d0 | Make sure MS bit is set 1258 move.b d0,cfr1(a0) | Update CFR1 image 1259 move.b d0,ACIA_CFR(a1) | Send CFR to hardware 1260 1260 rts 1261 * 1262 .page 1263 * 1264 *serintr -- Serial (Serial-1, Serial-2, MIDI-1, MIDI-2) interrupt handler1265 *------- -------------------------------------------------------------1266 serintr: movem.l d0-d3/a0-a2,-(a7) *Save registers1267 lea sr1iorec,a0 *Point at Serial-1 iorec1268 lea SR1ACIA,a1 *Point at Serial-1 ACIA1269 bsr serint *Go process (possible) int.1270 * 1271 lea sr2iorec,a0 *Point at Serial-2 iorec1272 lea SR2ACIA,a1 *Point at Serial-2 ACIA1273 bsr serint *Go process (possible) int.1274 * 1261 1262 .page 1263 1264 | serintr -- Serial (Serial-1, Serial-2, MIDI-1, MIDI-2) interrupt handler 1265 | ------- ------------------------------------------------------------- 1266 serintr: movem.l d0-d3/a0-a2,-(a7) | Save registers 1267 lea sr1iorec,a0 | Point at Serial-1 iorec 1268 lea SR1ACIA,a1 | Point at Serial-1 ACIA 1269 bsr serint | Go process (possible) int. 1270 1271 lea sr2iorec,a0 | Point at Serial-2 iorec 1272 lea SR2ACIA,a1 | Point at Serial-2 ACIA 1273 bsr serint | Go process (possible) int. 1274 1275 1275 .ifne BUCHLA 1276 * 1277 lea mc1iorec,a0 *Point at MIDI-1 iorec1278 lea MC1ACIA,a1 *Point at MIDI-1 ACIA1279 bsr midint *Go process (possible) int.1280 * 1281 lea mc2iorec,a0 *Point at MIDI-2 iorec1282 lea MC2ACIA,a1 *Point at MIDI-2 ACIA1283 bsr midint *Go process (possible) int.1284 * 1285 .endc 1286 * 1287 movem.l (a7)+,d0-d3/a0-a2 *Restore registers1288 rte *Return from exception1289 * 1290 .page 1291 * 1292 *serint -- Process an interrupt from Serial-1 or Serial-21293 *------ ----------------------------------------------1294 serint: move.b ACIA_ISR(a1),isr(a0) *Get and save ISR1295 move.b ACIA_CSR(a1),csr(a0) *Get and save CSR1296 * 1297 btst.b #7,isr(a0) *Was int for this device ?1298 beq serintx *Jump if not1299 * 1300 serchk: btst.b #1,isr(a0) *FRM/OVR/BRK error ?1301 bne sererr *Jump if so1302 * 1303 btst.b #0,isr(a0) *Receiver interrupt ?1304 bne serrx *Jump if so1305 * 1306 sertxq: btst.b #6,isr(a0) *Transmitter interrupt ?1307 bne sertx *Jump if so1308 * 1309 serctq: btst.b #5,isr(a0) *CTS interrupt ?1310 bne sercts *Jump if so1311 * 1312 serintx: rts *Return to caller1313 * 1314 sererr: addq.w #1,errct(a0) *Update error count1315 move.b ACIA_RDR(a1),erbyte(a0) *Get error byte1276 1277 lea mc1iorec,a0 | Point at MIDI-1 iorec 1278 lea MC1ACIA,a1 | Point at MIDI-1 ACIA 1279 bsr midint | Go process (possible) int. 1280 1281 lea mc2iorec,a0 | Point at MIDI-2 iorec 1282 lea MC2ACIA,a1 | Point at MIDI-2 ACIA 1283 bsr midint | Go process (possible) int. 1284 1285 .endc 1286 1287 movem.l (a7)+,d0-d3/a0-a2 | Restore registers 1288 rte | Return from exception 1289 1290 .page 1291 1292 | serint -- Process an interrupt from Serial-1 or Serial-2 1293 | ------ ---------------------------------------------- 1294 serint: 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 1300 serchk: 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 1306 sertxq: btst.b #6,isr(a0) | Transmitter interrupt ? 1307 bne sertx | Jump if so 1308 1309 serctq: btst.b #5,isr(a0) | CTS interrupt ? 1310 bne sercts | Jump if so 1311 1312 serintx: rts | Return to caller 1313 1314 sererr: addq.w #1,errct(a0) | Update error count 1315 move.b ACIA_RDR(a1),erbyte(a0) | Get error byte 1316 1316 rts 1317 * 1318 *Handle CTS interupt1319 * 1320 sercts: btst.b #1,linedisc(a0) *RTS/CTS mode ?1321 beq serintx *Ignore if not1322 * 1323 btst.b #5,csr(a0) *CTS set ?1324 beq serintx *Ignore if not1325 * 1326 sercts1: btst.b #6,isr(a0) *TDRE set ?1327 beq sercts1 *Loop until it is (!)1328 * 1329 move.w obufhd(a0),d2 *Head index to d21330 cmp.w obuftl(a0),d2 *Compare to tail index1331 beq serintx *Done if buffer empty1332 * 1333 bsr.w wrapout *Adjust pointer for wraparound1334 move.l obuf(a0),a2 *Get buffer base in a21335 move.b 0(a2,d2),ACIA_TDR(a1) *Send byte on its way1336 move.w d2,obufhd(a0) *Save updated head index1317 1318 | Handle CTS interupt 1319 1320 sercts: 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 1326 sercts1: btst.b #6,isr(a0) | TDRE set ? 1327 beq sercts1 | Loop until it is (!) 1328 1329 move.w obufhd(a0),d2 | Head index to d2 1330 cmp.w obuftl(a0),d2 | Compare to tail index 1331 beq serintx | Done if buffer empty 1332 1333 bsr.w wrapout | Adjust pointer for wraparound 1334 move.l obuf(a0),a2 | Get buffer base in a2 1335 move.b 0(a2,d2),ACIA_TDR(a1) | Send byte on its way 1336 move.w d2,obufhd(a0) | Save updated head index 1337 1337 rts 1338 * 1339 .page 1340 * 1341 *Handle receiver interrupt1342 * 1343 serrx: btst.b #1,linedisc(a0) *RTS/CTS mode set ?1344 beq serrx1 *Jump if not1345 * 1346 bsr.w rtsoff *Turn off RTS1347 * 1348 serrx1: move.b ACIA_RDR(a1),d0 *Read data from ACIA1349 btst.b #1,linedisc(a0) *RTS/CTS mode set ?1350 bne serrx3 *Jump if so1351 * 1352 btst.b #0,linedisc(a0) *XON/XOFF mode set ?1353 beq serrx3 *Jump if not1354 * 1355 cmpi.b # $11,d0 *Is this an XON ?1356 bne serrx2 *Jump if not1357 * 1358 move.b # $00,flagxoff(a0) *Clear flagxoff1359 bra sertxq *Done1360 * 1361 serrx2: cmpi.b # $13,d0 *Is this an XOFF ?1362 bne serrx3 *Jump if not1363 * 1364 move.b # $FF,flagxoff(a0) *Set flagxoff1365 bra sertxq *Done1366 * 1367 serrx3: move.w ibuftl(a0),d1 *Get tail index in d11368 bsr.w wrapin *Adjust for wraparound1369 cmp.w ibufhd(a0),d1 *Head = tail ?1370 beq seribf *If so, we drop the character1371 * 1372 move.l ibuf(a0),a2 *Get buffer address1373 move.b d0,0(a2,d1) *Stash byte in buffer1374 move.w d1,ibuftl(a0) *Save updated tail index1375 bsr rsilen *Get length of buffer used1376 cmp.w ibufhi(a0),d2 *Hit high water mark ?1377 bne serrx4 *Jump if not1378 * 1379 btst.b #1,linedisc(a0) *RTS/CTS mode set ?1380 bne sertxq *Done if so1381 * 1382 btst.b #0,linedisc(a0) *XON/XOFF mode set ?1383 beq serrx4 *Jump if not1384 * 1385 tst.b flagxon(a0) *XOFF already sent ?1386 bne serrx4 *Jump if so1387 * 1388 move.b # $FF,flagxon(a0) *Set the flag1389 move.b # $13,d1 *Send an XOFF1390 bsr.w serput *...1391 * 1392 .page 1393 * 1394 serrx4: btst #1,linedisc(a0) *RTS/CTS mode set ?1395 beq sertxq *Done if not1396 * 1397 bsr rtson *Turn on RTS1338 1339 .page 1340 1341 | Handle receiver interrupt 1342 1343 serrx: btst.b #1,linedisc(a0) | RTS/CTS mode set ? 1344 beq serrx1 | Jump if not 1345 1346 bsr.w rtsoff | Turn off RTS 1347 1348 serrx1: 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 1361 serrx2: 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 1367 serrx3: 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 1394 serrx4: btst #1,linedisc(a0) | RTS/CTS mode set ? 1395 beq sertxq | Done if not 1396 1397 bsr rtson | Turn on RTS 1398 1398 bra sertxq 1399 * 1400 *Handle transmitter interrupt1401 * 1402 sertx: btst.b #1,linedisc(a0) *RTS/CTS mode set ?1403 bne sertx2 *If so, go check CTS1404 * 1405 btst.b #0,linedisc(a0) *XON/XOFF mode set ?1406 beq sertx1 *Jump if not1407 * 1408 tst.b flagxoff(a0) *Check flagxoff1409 bne serctq *Done if set1410 * 1411 sertx1: move.w obufhd(a0),d2 *Head index to d21412 cmp.w obuftl(a0),d2 *Compare to tail index1413 beq serctq *Done if buffer empty1414 * 1415 bsr wrapout *Adjust pointer for wraparound1416 move.l obuf(a0),a2 *Get buffer base address1417 move.b 0(a2,d2),ACIA_TDR(a1) *Send byte on its way1418 move.w d2,obufhd(a0) *Save updated head index1419 bra serctq *Done1420 * 1421 sertx2: btst.b #5,csr(a0) *CTS set in csr ?1422 beq serctq *If not, go check for CTS int1423 * 1424 bra sertx1 *CTS was set, go transmit1425 * 1426 seribf: move.b d0,erbyte(a0) *Log dropped character1427 addq.w #1,ibfct(a0) *...1428 bra sertxq *Go check Tx interrupt1429 * 1430 .page 1431 * 1399 1400 | Handle transmitter interrupt 1401 1402 sertx: 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 1411 sertx1: 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 1421 sertx2: 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 1426 seribf: move.b d0,erbyte(a0) | Log dropped character 1427 addq.w #1,ibfct(a0) | ... 1428 bra sertxq | Go check Tx interrupt 1429 1430 .page 1431 1432 1432 .ifne BUCHLA 1433 * 1434 *midint -- Process an interrupt from MIDI-1 or MIDI-21435 *------ ------------------------------------------1436 midint: move.b ACIA_ISR(a1),isr(a0) *Get and save ISR1437 move.b ACIA_CSR(a1),csr(a0) *Get and save CSR1438 * 1439 btst.b #7,isr(a0) *Was int for this device ?1440 beq midintx *Jump if not1441 * 1442 midchk: btst.b #1,isr(a0) *FRM/OVR/BRK error ?1443 bne miderr *Jump if so1444 * 1445 btst.b #0,isr(a0) *Receiver interrupt ?1446 bne midrx *Jump if so1447 * 1448 midtxq: btst.b #6,isr(a0) *Transmitter interrupt ?1449 bne midtx *Jump if so1450 * 1451 midintx: rts *Return to caller1452 * 1453 miderr: addq.w #1,errct(a0) *Update error count1454 move.b ACIA_RDR(a1),erbyte(a0) *Get error byte1433 1434 | midint -- Process an interrupt from MIDI-1 or MIDI-2 1435 | ------ ------------------------------------------ 1436 midint: 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 1442 midchk: 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 1448 midtxq: btst.b #6,isr(a0) | Transmitter interrupt ? 1449 bne midtx | Jump if so 1450 1451 midintx: rts | Return to caller 1452 1453 miderr: addq.w #1,errct(a0) | Update error count 1454 move.b ACIA_RDR(a1),erbyte(a0) | Get error byte 1455 1455 rts 1456 * 1457 *Handle receiver interrupt1458 * 1459 midrx: move.b ACIA_RDR(a1),d0 *Read data from ACIA1460 move.w ibuftl(a0),d1 *Get tail index in d11461 bsr.w wrapin *Adjust for wraparound1462 cmp.w ibufhd(a0),d1 *Head = tail ?1463 beq midibf *If so, we drop the character1464 * 1465 move.l ibuf(a0),a2 *Get buffer address1466 move.b d0,0(a2,d1) *Stash byte in buffer1467 move.w d1,ibuftl(a0) *Save updated tail index1468 bra midtxq *Done (go check tx int)1469 * 1470 .page 1471 * 1472 *Handle transmitter interrupt1473 * 1474 midtx: move.w obufhd(a0),d2 *Head index to d21475 cmp.w obuftl(a0),d2 *Compare to tail index1476 beq midintx *Done if buffer empty1477 * 1478 bsr wrapout *Adjust pointer for wraparound1479 move.l obuf(a0),a2 *Get buffer base address1480 move.b 0(a2,d2),ACIA_TDR(a1) *Send byte on its way1481 move.w d2,obufhd(a0) *Save updated head index1482 bra midintx *Done1483 * 1484 midibf: move.b d0,erbyte(a0) *Log dropped character1485 addq.w #1,ibfct(a0) *...1486 bra midtxq *Go check Tx interrupt1487 * 1488 .endc 1489 * 1490 .page 1491 * 1492 *setexec -- Set an exception vector1493 *------- -----------------------1494 setexec: move.w 4(a7),d0 *Get vector number1495 lsl.w #2,d0 *.. times 41496 sub.l a0,a0 *Clear a01497 lea 0(a0,d0),a0 *Get address of old vector1498 move.l (a0),d0 *Move old vector to d01499 move.l 6(a7),d1 *Pick up new vector1500 bmi setexec1 *Don't set if = -11501 * 1502 move.l d1,(a0) *Set new vector1503 * 1504 setexec1: rts *Return to caller1505 * 1506 *piorec -- Get pointer to iorec structure1507 *------ ------------------------------1508 piorec: moveq.l #0,d1 *Clear out d11509 move.w 4(a7),d1 *Get device number1510 move.w sr,-(a7) *Save status register1511 ori.w #IPL7,sr *Set IPL = 7 (no ints)1512 lea iortab,a2 *Get base address of table1513 asl.l #2,d1 *Device # times 4 for index1514 move.l 0(a2,d1),d0 *Get iorec address from table1515 move.w (a7)+,sr *Restore status register1516 rts *Return to caller1517 * 1518 .page 1519 * 1520 *setport -- Set ACIA parameters (unit, mode, baud, CFR0, CFR1)1521 *------- ---------------------------------------------------1522 setport: moveq.l #0,d1 *Clear out d11523 move.w 4(a7),d1 *Get device number1524 asl.l #3,d1 *Times 8 for index1525 ori.w #IPL7,sr *Set IPL = 7 (no ints)1526 lea aciatab,a2 *Get base of table1527 move.l 0(a2,d1),d0 *Get iorec address1528 move.l 4(a2,d1),d2 *Get ACIA address1529 movea.l d0,a0 *Setup a0 = iorec address1530 movea.l d2,a1 *Setup a1 = ACIA address1531 tst.w 6(a7) *Change mode ?1532 bmi setpt1 *Jump if not1533 * 1534 move.b 7(a7),linedisc(a0) *Set line discipline (mode)1535 * 1536 setpt1: tst.w 8(a7) *Change baud rate ?1537 bmi setpt2 *Jump if not1538 * 1539 moveq.l #0,d1 *Clear out d11540 move.w 8(a7),d1 *Get baud rate index1541 lea brtable,a2 *Get base of baud rate table1542 move.b 0(a2,d1),d2 *Get baud rate code from table1543 move.b cfr0(a0),d0 *Get current CFR01544 andi.w # $0070,d0 *Mask off old baud rate code1545 or.w d2,d0 *OR in new baud rate code1546 move.b d0,cfr0(a0) *Update CFR0 in table1547 move.b d0,ACIA_CFR(a1) *Update hardware1548 * 1549 setpt2: tst.w 10(a7) *Change CFR0 ?1550 bmi setpt3 *Jump if not1551 * 1552 move.b 11(a7),cfr0(a0) *Update CFR0 in table1553 move.b cfr0(a0),ACIA_CFR(a1) *Update CFR0 in hardware1554 * 1555 setpt3: tst.w 12(a7) *Change CFR1 ?1556 bmi setpt4 *Jump if not1557 * 1558 bset.b #7,13(a7) *Force D7 = 1 in argument1559 move.b 13(a7),cfr1(a0) *Update CFR1 in table1560 move.b cfr1(a0),ACIA_CFR(a1) *Update CFR1 in hardware1561 * 1562 setpt4: rts *Return to caller1563 * 1564 .page 1565 * 1566 *aciainit -- Initialize an ACIA port1567 *-------- -----------------------1568 aciainit: move.w #IORECLN,d0 *Setup byte count for move1569 move.l a0,-(a7) *Save iorec base1570 * 1571 aciai_1: move.b (a2)+,(a0)+ *Move the default to the iorec1572 dbf d0,aciai_1 *...1573 * 1574 move.l (a7)+,a0 *Restore iorec base1575 move.b cfr0(a0),ACIA_CFR(a1) *Setup CFR01576 move.b cfr1(a0),ACIA_CFR(a1) *Setup CFR11577 move.b ACIA_RDR(a1),d0 *Clear RDR1578 move.b # $7F,ACIA_IER(a1) *Disable all interrupts1579 btst.b #1,linedisc(a0) *Are we in RTS/CTS mode ?1580 bne aciai_2 *Jump if so1581 * 1582 move.b # $C3,ACIA_IER(a1) *Enable TDRE, RDRF1583 bra aciai_3 *Go return1584 * 1585 aciai_2: move.b # $E3,ACIA_IER(a1) *Enable interrupts we want1586 * 1587 aciai_3: rts *Return to caller1588 * 1589 .page 1590 * 1456 1457 | Handle receiver interrupt 1458 1459 midrx: 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 1474 midtx: 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 1484 midibf: move.b d0,erbyte(a0) | Log dropped character 1485 addq.w #1,ibfct(a0) | ... 1486 bra midtxq | Go check Tx interrupt 1487 1488 .endc 1489 1490 .page 1491 1492 | setexec -- Set an exception vector 1493 | ------- ----------------------- 1494 setexec: 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 1504 setexec1: rts | Return to caller 1505 1506 | piorec -- Get pointer to iorec structure 1507 | ------ ------------------------------ 1508 piorec: 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 | ------- --------------------------------------------------- 1522 setport: 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 1536 setpt1: 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 1549 setpt2: 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 1555 setpt3: 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 1562 setpt4: rts | Return to caller 1563 1564 .page 1565 1566 | aciainit -- Initialize an ACIA port 1567 | -------- ----------------------- 1568 aciainit: move.w #IORECLN,d0 | Setup byte count for move 1569 move.l a0,-(a7) | Save iorec base 1570 1571 aciai_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 1585 aciai_2: move.b #0xE3,ACIA_IER(a1) | Enable interrupts we want 1586 1587 aciai_3: rts | Return to caller 1588 1589 .page 1590 1591 1591 .ifne BUCHLA 1592 * 1593 *fastcopy -- Copy disk sector quickly1594 *-------- ------------------------1595 fastcopy: move.l 4(a7),a0 *Get source pointer1596 move.l 8(a7),a1 *Get destination pointer1597 move.w $3F,d0 * 512 bytes (63+1)*81598 * 1599 fastcpy1: move.b (a0)+,(a1)+ *Move 8 bytes1600 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 moved1608 * 1609 rts *Return to caller1610 * 1611 .page 1612 * 1613 *_hdvini -- Drive initialization1614 *------- --------------------1615 _hdvini: link a6,#-18 *Reserve space on stack1616 movem.l d3-d7/a3-a5,-(a7) *Preserve registers1617 move.l #300,maxactim * maxactim = 300 *20ms1618 clr.w d0 *Put zeros in ...1619 move.w d0,nflops *... nflops1620 move.w d0,dskmode *... dskmode1621 move.w d0,-2(a6) *Start with drive A1622 bra hdvilp *...1623 * 1624 hdvilp1: movea.l #dskmode,a0 *Get dskmode address in a01625 movea.w -2(a6),a1 *Drive number in a11626 adda.l a1,a0 *Point at dskmode for drive1627 clr.b (a0) *Clear flag in dskmode1628 clr.w -(a7) *Push arguments onto stack1629 clr.w -(a7) *...1630 clr.w -(a7) *...1631 move.w -2(a6),-(a7) *Push drive number onto stack1632 clr.l -(a7) *... filler1633 clr.l -(a7) *... filler1634 jsr flopini *Initialize drive1635 adda.l #16,a7 *Cleanup stack1636 move.w d0,-(a7) *Save error code on stack1637 movea.w -2(a6),a0 *Get drive number1638 adda.l a0,a0 *... times 21639 adda.l #dskerrs,a0 *Add base of dskerrs1640 move.w (a7)+,(a0) *Move error code off of stack1641 bne hdvind *Jump if drive not present1642 * 1643 addq.w #1,nflops *Update number of drives1644 or.l #3,drvbits *Setup drive bits1645 * 1646 hdvind: addq.w #1,-2(a6) *Increment drive number1647 * 1648 hdvilp: cmp.w #2,-2(a6) *See if it's 2 yet1649 blt hdvilp1 *Loop until it is1650 * 1651 movem.l (a7)+,d3-d7/a3-a5 *Restore registers1652 unlk a6 *Release temporary stack space1653 rts *Return to caller1654 * 1655 *drvmap -- get drive map1656 *------ -------------1657 drvmap: move.l drvbits,d0 *Get drive bits1658 rts *Return to caller1659 * 1660 .page 1661 * 1662 *getbpb -- get BIOS parameter block1663 *------ ------------------------1664 getbpb: link a6,#-12 *Reserve space for temporaries1665 movem.l d5-d7/a4-a5,-(a7) *Save registers on stack1666 cmp.w #2,8(a6) *Check drive number1667 blt gbpb1 *Jump if OK1668 * 1669 clr.l d0 *Set drive number to 01670 bra gbpber *Go flag error1671 * 1672 gbpb1: move.w 8(a6),d0 *Get drive number1673 asl.w #5,d0 *... times 321674 ext.l d0 *... extend sign1675 move.l d0,a5 *Move to a51676 add.l #drvbpbs,a5 *Add base of drive bpb are1677 move.l a5,a4 *Save in a41678 * 1679 gbpbrds: 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) *... filler1685 move.l #buffer,-(a7) *... buffer address,1686 jsr floprd *Go read the sector1687 add.l #16,a7 *Cleanup stack1688 move.l d0,-12(a6) *Save error code1689 tst.l -12(a6) *... and test it1690 bge gbpb2 *Jump if OK1691 * 1692 move.w 8(a6),(a7) *Put drive number on stack1693 move.l -12(a6),d0 *Get error code1694 move.w d0,-(a7) *... and put it on the stack1695 jsr criter *Go do critical error routine1696 addq.l #2,a7 *Cleanup stack1697 move.l d0,-12(a6) *Save error code1698 * 1699 gbpb2: move.l -12(a6),d0 *Get error code1700 cmp.l #RETRYIT,d0 *Magic number for retry ?1701 beq gbpbrds *Re-read if so1702 * 1703 tst.l -12(a6) *Test error code1704 bge gbpb3 *Jump if OK1705 * 1706 clr.l d0 *Set code in d01707 bra gbpber *Go set error code1708 * 1709 .page 1710 * 1711 gbpb3: move.l #buffer+11,(a7) *Bytes per sector1712 bsr itom *Convert 8086 to 68K format1713 move.w d0,d7 *Save bytes per sector1714 beq gbpb4 *Jump if zero1715 * 1716 move.b buffer+13,d6 *Sectors per cluster1717 ext.w d6 *... sign extended1718 and.w # $FF,d6 *... and trimmed1719 bne gbpb5 *Jump if non-zero1720 * 1721 gbpb4: clr.l d0 *Set error code1722 bra gbpber *...1723 * 1724 gbpb5: move.w d7,(a4) *Set recsize1725 move.w d6,2(a4) *Set clsiz1726 move.l #buffer+22,(a7) *Convert sectors per fat1727 bsr itom *...1728 move.w d0,8(a4) *Set fsiz1729 move.w 8(a4),d0 *Get fsiz1730 addq.w #1,d0 *... plus 11731 move.w d0,10(a4) *Set fatrec1732 move.w (a4),d0 *Get recsize1733 muls.w 2(a4),d0 *... times clsiz1734 move.w d0,4(a4) *Set clsizb1735 move.l #buffer+17,(a7) *Convert number of dir ents1736 bsr itom *...1737 asl.w #5,d0 *... times 321738 ext.l d0 *... sign extended1739 divs.w (a4),d0 *... / recsize1740 move.w d0,6(a4) *Set rdlen1741 move.w 10(a4),d0 *Get fatrec1742 add.w 6(a4),d0 *... + rdlen1743 add.w 8(a4),d0 *... + fsiz1744 move.w d0,12(a4) *Set datrec1745 move.l #buffer+19,(a7) *Get number of sectors1746 bsr itom *... convert1747 sub.w 12(a4),d0 *... - datrec1748 ext.l d0 *... sign extended1749 divs.w 2(a4),d0 *... / clsiz1750 move.w d0,14(a4) *Set numcl1751 * 1752 .page 1753 * 1754 move.l #buffer+26,(a7) *Convert number of heads1755 bsr itom *...1756 move.w d0,20(a5) *Set dnsides1757 move.l #buffer+24,(a7) *Convert sectors per track1758 bsr itom *...1759 move.w d0,24(a5) *Set dspt1760 move.w 20(a5),d0 *Get dnsides1761 muls.w 24(a5),d0 * ... *dspt1762 move.w d0,22(a5) *Set dspc1763 move.l #buffer+28,(a7) *Convert number of hidden sects1764 bsr itom *...1765 move.w d0,26(a5) *Set dhidden1766 move.l #buffer+19,(a7) *Convert sectors on disk1767 bsr itom *...1768 ext.l d0 *... sign extended1769 divs.w 22(a5),d0 *... / dspc1770 move.w d0,18(a5) *Set dntracks1771 clr.w d7 *Counter = 01772 bra gbpblpt *Jump to end of loop1773 * 1774 gbpb6: move.l a5,a0 *Get buffer pointer1775 move.w d7,a1 *Loop count to a11776 add.l a1,a0 *... + bpb address1777 move.w d7,a1 *Loop count to a11778 add.l #buffer,a1 *... + buffer address1779 move.b 8(a1),28(a0) *Copy a s/n byte1780 addq.w #1,d7 *Update loop count1781 * 1782 gbpblpt: cmp.w #3,d7 *Moved 3 bytes ?1783 blt gbpb6 *Loop if not1784 * 1785 .page 1786 * 1787 move.l #cdev,a0 *Address of cdev table1788 move.w 8(a6),a1 *... plus drive number1789 add.l a1,a0 *... to a01790 move.l #wpstatus,a1 *Address of wpstatus table1791 move.w 8(a6),a2 *... plus drive number1792 add.l a2,a1 *... to a11793 move.b (a1),(a0) *Move wpstatus to cdev1592 1593 | fastcopy -- Copy disk sector quickly 1594 | -------- ------------------------ 1595 fastcopy: move.l 4(a7),a0 | Get source pointer 1596 move.l 8(a7),a1 | Get destination pointer 1597 move.w 0x3F,d0 | 512 bytes (63+1)|8 1598 1599 fastcpy1: move.b (a0)+,(a1)+ | Move 8 bytes 1600 move.b (a0)+,(a1)+ | ... 1601 move.b (a0)+,(a1)+ | ... 1602 move.b (a0)+,(a1)+ | ... 1603 move.b (a0)+,(a1)+ | ... 1604 move.b (a0)+,(a1)+ | ... 1605 move.b (a0)+,(a1)+ | ... 1606 move.b (a0)+,(a1)+ | ... 1607 dbra d0,fastcpy1 | Loop until all bytes are moved 1608 1609 rts | Return to caller 1610 1611 .page 1612 1613 | _hdvini -- Drive initialization 1614 | ------- -------------------- 1615 _hdvini: link a6,#-18 | Reserve space on stack 1616 movem.l d3-d7/a3-a5,-(a7) | Preserve registers 1617 move.l #300,maxactim | maxactim = 300 | 20ms 1618 clr.w d0 | Put zeros in ... 1619 move.w d0,nflops | ... nflops 1620 move.w d0,dskmode | ... dskmode 1621 move.w d0,-2(a6) | Start with drive A 1622 bra hdvilp | ... 1623 1624 hdvilp1: 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 1646 hdvind: addq.w #1,-2(a6) | Increment drive number 1647 1648 hdvilp: 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 | ------ ------------- 1657 drvmap: move.l drvbits,d0 | Get drive bits 1658 rts | Return to caller 1659 1660 .page 1661 1662 | getbpb -- get BIOS parameter block 1663 | ------ ------------------------ 1664 getbpb: 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 1672 gbpb1: 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 1679 gbpbrds: 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 1699 gbpb2: 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 1711 gbpb3: 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 1721 gbpb4: clr.l d0 | Set error code 1722 bra gbpber | ... 1723 1724 gbpb5: move.w d7,(a4) | Set recsize 1725 move.w d6,2(a4) | Set clsiz 1726 move.l #buffer+22,(a7) | Convert sectors per fat 1727 bsr itom | ... 1728 move.w d0,8(a4) | Set fsiz 1729 move.w 8(a4),d0 | Get fsiz 1730 addq.w #1,d0 | ... plus 1 1731 move.w d0,10(a4) | Set fatrec 1732 move.w (a4),d0 | Get recsize 1733 muls.w 2(a4),d0 | ... times clsiz 1734 move.w d0,4(a4) | Set clsizb 1735 move.l #buffer+17,(a7) | Convert number of dir ents 1736 bsr itom | ... 1737 asl.w #5,d0 | ... times 32 1738 ext.l d0 | ... sign extended 1739 divs.w (a4),d0 | ... / recsize 1740 move.w d0,6(a4) | Set rdlen 1741 move.w 10(a4),d0 | Get fatrec 1742 add.w 6(a4),d0 | ... + rdlen 1743 add.w 8(a4),d0 | ... + fsiz 1744 move.w d0,12(a4) | Set datrec 1745 move.l #buffer+19,(a7) | Get number of sectors 1746 bsr itom | ... convert 1747 sub.w 12(a4),d0 | ... - datrec 1748 ext.l d0 | ... sign extended 1749 divs.w 2(a4),d0 | ... / clsiz 1750 move.w d0,14(a4) | Set numcl 1751 1752 .page 1753 1754 move.l #buffer+26,(a7) | Convert number of heads 1755 bsr itom | ... 1756 move.w d0,20(a5) | Set dnsides 1757 move.l #buffer+24,(a7) | Convert sectors per track 1758 bsr itom | ... 1759 move.w d0,24(a5) | Set dspt 1760 move.w 20(a5),d0 | Get dnsides 1761 muls.w 24(a5),d0 | ... | dspt 1762 move.w d0,22(a5) | Set dspc 1763 move.l #buffer+28,(a7) | Convert number of hidden sects 1764 bsr itom | ... 1765 move.w d0,26(a5) | Set dhidden 1766 move.l #buffer+19,(a7) | Convert sectors on disk 1767 bsr itom | ... 1768 ext.l d0 | ... sign extended 1769 divs.w 22(a5),d0 | ... / dspc 1770 move.w d0,18(a5) | Set dntracks 1771 clr.w d7 | Counter = 0 1772 bra gbpblpt | Jump to end of loop 1773 1774 gbpb6: 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 1782 gbpblpt: cmp.w #3,d7 | Moved 3 bytes ? 1783 blt gbpb6 | Loop if not 1784 1785 .page 1786 1787 move.l #cdev,a0 | Address of cdev table 1788 move.w 8(a6),a1 | ... plus drive number 1789 add.l a1,a0 | ... to a0 1790 move.l #wpstatus,a1 | Address of wpstatus table 1791 move.w 8(a6),a2 | ... plus drive number 1792 add.l a2,a1 | ... to a1 1793 move.b (a1),(a0) | Move wpstatus to cdev 1794 1794 beq gbpb7 1795 * 1796 moveq.l #1,d0 *Set status = "Uncertain"1795 1796 moveq.l #1,d0 | Set status = "Uncertain" 1797 1797 bra gbpb8 1798 * 1799 gbpb7: clr.w d0 *Set status = "Unchanged"1800 * 1801 gbpb8: move.l #dskmode,a1 *Update dskmode table1802 move.w 8(a6),a2 *...1803 add.l a2,a1 *...1804 move.b d0,(a1) *...1805 move.l a5,d0 *Setup to return bpb pointer1806 * 1807 gbpber: tst.l (a7)+ *Pop garbage off top of stack1808 movem.l (a7)+,d6-d7/a4-a5 *Restore registers1798 1799 gbpb7: clr.w d0 | Set status = "Unchanged" 1800 1801 gbpb8: 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 1807 gbpber: tst.l (a7)+ | Pop garbage off top of stack 1808 movem.l (a7)+,d6-d7/a4-a5 | Restore registers 1809 1809 unlk a6 1810 1810 rts 1811 * 1812 .page 1813 * 1814 *mediach -- check for media change1815 *------- ----------------------1816 mediach: link a6,#0 *Create scratch on stack1817 movem.l d6-d7/a5,-(a7) *Save registers on stack1818 cmp.w #2,8(a6) *Check drive number1819 blt media1 *Jump if OK1820 * 1821 moveq.l #ERR15,d0 *Error -- "unknown device"1822 bra media2 *...1823 * 1824 media1: move.w 8(a6),d7 *Get drive number in d71825 movea.w d7,a5 *Point into dskmode table1826 add.l #dskmode,a5 *...1827 cmp.b #2,(a5) *Definitely changed ?1828 bne media3 *Jump if not1829 * 1830 moveq.l #2,d0 *Setup to return "Changed"1831 bra media2 *Done -- go return to caller1832 * 1833 media3: move.l #wplatch,a0 *Check wplatch for drive1834 tst.b 0(a0,d7) *...1835 beq media4 *Jump if not set1836 * 1837 move.b #1,(a5) *Set dskmode to "Uncertain"1838 * 1839 media4: move.l _hz_200,d0 *Get time in d01840 movea.w d7,a1 *Calculate acctim table address1841 add.l a1,a1 * ... = drive # *41842 add.l a1,a1 *...1843 add.l #acctim,a1 *... + acctim base address1844 move.l (a1),d1 *Get acctim for drive1845 sub.l d1,d0 *Subtract from current time1846 cmp.l maxactim,d0 *Timed out ?1847 bge media5 *Jump if so1848 * 1849 clr.w d0 *Setup to return "Unchanged"1811 1812 .page 1813 1814 | mediach -- check for media change 1815 | ------- ---------------------- 1816 mediach: 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 1824 media1: 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 1833 media3: 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 1839 media4: move.l _hz_200,d0 | Get time in d0 1840 movea.w d7,a1 | Calculate acctim table address 1841 add.l a1,a1 | ... = drive # | 4 1842 add.l a1,a1 | ... 1843 add.l #acctim,a1 | ... + acctim base address 1844 move.l (a1),d1 | Get acctim for drive 1845 sub.l d1,d0 | Subtract from current time 1846 cmp.l maxactim,d0 | Timed out ? 1847 bge media5 | Jump if so 1848 1849 clr.w d0 | Setup to return "Unchanged" 1850 1850 bra media2 1851 * 1852 media5: move.b (a5),d0 *Return status from dskmode1851 1852 media5: move.b (a5),d0 | Return status from dskmode 1853 1853 ext.w d0 1854 * 1855 media2: tst.l (a7)+ *Pop extra stack word1856 movem.l (a7)+,d7/a5 *Restore registers1854 1855 media2: tst.l (a7)+ | Pop extra stack word 1856 movem.l (a7)+,d7/a5 | Restore registers 1857 1857 unlk a6 1858 rts *Return to caller1859 * 1860 .page 1861 * 1862 *rwabs -- read / write sector(s)1863 *----- ----------------------1864 rwabs: link a6,#-4 *Reserve stack for temps1865 movem.l d4-d7/a5,-(a7) *Save registers on stack1866 cmp.w #2,18(a6) *Drive number1858 rts | Return to caller 1859 1860 .page 1861 1862 | rwabs -- read / write sector(s) 1863 | ----- ---------------------- 1864 rwabs: link a6,#-4 | Reserve stack for temps 1865 movem.l d4-d7/a5,-(a7) | Save registers on stack 1866 cmp.w #2,18(a6) | Drive number 1867 1867 blt rwabs1 1868 * 1869 moveq.l #ERR15,d0 *ERROR -- "unknown device"1868 1869 moveq.l #ERR15,d0 | ERROR -- "unknown device" 1870 1870 bra rwabser 1871 * 1872 rwabs1: move.w 18(a6),d6 *Save drive number1873 cmp.w #2,8(a6) *Check rwflag1871 1872 rwabs1: move.w 18(a6),d6 | Save drive number 1873 cmp.w #2,8(a6) | Check rwflag 1874 1874 bge rwabs7 1875 * 1875 1876 1876 move.w d6,d0 1877 1877 asl.w #5,d0 … … 1880 1880 add.l #drvbpbs,a5 1881 1881 move.w d6,(a7) 1882 bsr mediach *Test for media change1883 move.w d0,d7 *Save status1884 cmp.w #2,d7 *Disk changed ?1885 bne rwabs2 *Jump if not1886 * 1887 moveq.l #ERR14,d0 *ERROR -- "media changed"1888 bra rwabser *...1889 * 1890 rwabs2: cmp.w #1,d7 *Disk possibly changed ?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 1890 rwabs2: cmp.w #1,d7 | Disk possibly changed ? 1891 1891 bne rwabs7 1892 * 1893 rwabs3: 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 sector1901 add.l #16,a7 *Cleanup stack1902 move.l d0,-4(a6) *Save error number1903 tst.l -4(a6) *... and test it1904 bge rwabs11 *Jump if OK1905 * 1906 .page 1907 * 1892 1893 rwabs3: move.w #1,(a7) | floprd count = 1, 1894 clr.w -(a7) | ... side = 0, 1895 clr.w -(a7) | ... track = 0, 1896 move.w #1,-(a7) | ... sector = 1, 1897 move.w d6,-(a7) | ... drive number, 1898 clr.l -(a7) | ... filler, 1899 move.l #buffer,-(a7) | ... buffer address, 1900 jsr floprd | Read boot sector 1901 add.l #16,a7 | Cleanup stack 1902 move.l d0,-4(a6) | Save error number 1903 tst.l -4(a6) | ... and test it 1904 bge rwabs11 | Jump if OK 1905 1906 .page 1907 1908 1908 move.w d6,(a7) 1909 1909 move.l -4(a6),d0 1910 1910 move.w d0,-(a7) 1911 jsr criter *Call critical error code1912 addq.l #2,a7 *Cleanup stack1911 jsr criter | Call critical error code 1912 addq.l #2,a7 | Cleanup stack 1913 1913 move.l d0,-4(a6) 1914 * 1914 1915 1915 rwabs11: move.l -4(a6),d0 1916 1916 cmp.l #RETRYIT,d0 1917 beq rwabs3 *Read again1918 * 1919 tst.l -4(a6) *Test error number1920 bge rwabs4 *OK ?1921 * 1917 beq rwabs3 | Read again 1918 1919 tst.l -4(a6) | Test error number 1920 bge rwabs4 | OK ? 1921 1922 1922 move.l -4(a6),d0 1923 bra rwabser *ERROR1924 * 1925 rwabs4: clr.w d7 *Clear media change status1923 bra rwabser | ERROR 1924 1925 rwabs4: clr.w d7 | Clear media change status 1926 1926 bra rwabs10 1927 * 1928 rwabs6: move.l #buffer,a0 *Address of sector buffer to a01929 move.b 8(a0,d7),d0 *Serial number1927 1928 rwabs6: move.l #buffer,a0 | Address of sector buffer to a0 1929 move.b 8(a0,d7),d0 | Serial number 1930 1930 ext.w d0 1931 move.b 28(a5,d7),d1 *Compare to old one1931 move.b 28(a5,d7),d1 | Compare to old one 1932 1932 ext.w d1 1933 1933 cmp.w d1,d0 1934 beq rwabs5 *Jump if they're the same1935 * 1936 moveq.l #ERR14,d0 *ERROR -- "media changed"1934 beq rwabs5 | Jump if they're the same 1935 1936 moveq.l #ERR14,d0 | ERROR -- "media changed" 1937 1937 bra rwabser 1938 * 1939 rwabs5: addq.w #1,d7 *Next byte of serial number1940 * 1941 rwabs10: cmp.w #3,d7 *All 3 bytes checked ?1942 blt rwabs6 *Loop if not1943 * 1944 .page 1945 * 1946 move.w d6,a0 *Point at wplatch for drive1947 add.l #wplatch,a0 *...1948 move.w d6,a1 *Point at wpstatus for drive1949 add.l #wpstatus,a1 *...1950 move.b (a1),(a0) *Move wpstatus to wplatch1951 bne rwabs9 *Jump if set1952 * 1953 move.w d6,a0 *Set dskmode to "Unchanged"1954 add.l #dskmode,a0 *...1955 clr.b (a0) *...1956 * 1957 rwabs7: tst.w nflops *Test nflops1938 1939 rwabs5: addq.w #1,d7 | Next byte of serial number 1940 1941 rwabs10: 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 1957 rwabs7: tst.w nflops | Test nflops 1958 1958 bne rwabs8 1959 * 1960 moveq.l #ERR02,d0 *ERROR -- "drive not ready"1959 1960 moveq.l #ERR02,d0 | ERROR -- "drive not ready" 1961 1961 bra rwabser 1962 * 1963 rwabs8: cmp.w #1,8(a6) *Check rwflag1962 1963 rwabs8: cmp.w #1,8(a6) | Check rwflag 1964 1964 ble rwabs9 1965 * 1966 subq.w #2,8(a6) *Adjust to 0|11967 * 1968 rwabs9: 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) *... rwflag1973 bsr floprw *Call floprw1974 * 1975 add.l #10,a7 *Cleanup stack1976 * 1977 rwabser: tst.l (a7)+ *Pop stack scratch1978 movem.l (a7)+,d5-d7/a5 *Restore registers1979 unlk a6 *Release temporaries1980 rts *Return to caller1981 * 1982 .page 1983 * 1984 *floprw -- Floppy read / write driver1985 *------ --------------------------1986 floprw: link a6,#-6 *Reserve space for temps1987 movem.l d2-d7/a5,-(a7) *Save registers1988 move.w 16(a6),d0 *Drive number to d01989 asl.w #5,d0 * Shift ( *32 )1990 ext.l d0 *Sign extend it, too1991 move.l d0,a5 *Result in a51992 add.l #drvbpbs,a5 *Add base of BPB table1993 btst #0,13(a6) *Buffer address even ?1994 bne floprw01 *Jump if not1995 * 1996 clr.w d0 *Clear odd flag1997 bra floprw02 *Go save the flag1998 * 1999 floprw01: moveq.l #1,d0 *Set odd flag2000 * 2001 floprw02: move.w d0,-2(a6) *Save it2002 tst.w 22(a5) *dspc set ?2003 bne floprw20 *Jump if so2004 * 2005 moveq.l #9,d0 *Assume 92006 move.w d0,22(a5) *... and make it the default2007 move.w d0,24(a5) *... for dspt and dspc2008 * 1965 1966 subq.w #2,8(a6) | Adjust to 0|1 1967 1968 rwabs9: 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 1977 rwabser: 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 | ------ -------------------------- 1986 floprw: link a6,#-6 | Reserve space for temps 1987 movem.l d2-d7/a5,-(a7) | Save registers 1988 move.w 16(a6),d0 | Drive number to d0 1989 asl.w #5,d0 | Shift ( |32 ) 1990 ext.l d0 | Sign extend it, too 1991 move.l d0,a5 | Result in a5 1992 add.l #drvbpbs,a5 | Add base of BPB table 1993 btst #0,13(a6) | Buffer address even ? 1994 bne floprw01 | Jump if not 1995 1996 clr.w d0 | Clear odd flag 1997 bra floprw02 | Go save the flag 1998 1999 floprw01: moveq.l #1,d0 | Set odd flag 2000 2001 floprw02: 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 2009 2009 floprw20: bra floprw18 2010 * 2011 floprw03: tst.w -2(a6) *Is odd flag set ?2012 beq floprw04 *Jump if not2013 * 2014 move.l #buffer,d0 *Point to sector buffer2010 2011 floprw03: tst.w -2(a6) | Is odd flag set ? 2012 beq floprw04 | Jump if not 2013 2014 move.l #buffer,d0 | Point to sector buffer 2015 2015 bra floprw05 2016 * 2017 floprw04: move.l 10(a6),d0 *Get buffer address2018 * 2019 floprw05: move.l d0,-6(a6) *... and save2020 move.w 14(a6),d6 *Get recno (lsn)2021 ext.l d6 *Extend it to long2022 divs.w 22(a5),d6 *Divide by dspc for track #2023 move.w 14(a6),d4 *Get recno2024 ext.l d4 *Extend to long2025 divs.w 22(a5),d4 *Divide by dspc2026 swap d4 *Use remainder as sector number2027 cmp.w 24(a5),d4 *Compare with dspt2028 bge floprw06 *Greater than or equal ?2029 * 2030 clr.l d5 *Use side 02016 2017 floprw04: move.l 10(a6),d0 | Get buffer address 2018 2019 floprw05: move.l d0,-6(a6) | ... and save 2020 move.w 14(a6),d6 | Get recno (lsn) 2021 ext.l d6 | Extend it to long 2022 divs.w 22(a5),d6 | Divide by dspc for track # 2023 move.w 14(a6),d4 | Get recno 2024 ext.l d4 | Extend to long 2025 divs.w 22(a5),d4 | Divide by dspc 2026 swap d4 | Use remainder as sector number 2027 cmp.w 24(a5),d4 | Compare with dspt 2028 bge floprw06 | Greater than or equal ? 2029 2030 clr.l d5 | Use side 0 2031 2031 bra floprw07 2032 * 2033 floprw06: moveq.l #1,d5 *Use side 12034 sub.w 24(a5),d4 *Subtract dspt from sector #2035 * 2036 .page 2037 * 2038 floprw07: tst.w -2(a6) *Is odd flag set ?2039 beq floprw08 *Jump if not2040 * 2041 moveq.l #1,d3 *Set counter to 12032 2033 floprw06: moveq.l #1,d5 | Use side 1 2034 sub.w 24(a5),d4 | Subtract dspt from sector # 2035 2036 .page 2037 2038 floprw07: tst.w -2(a6) | Is odd flag set ? 2039 beq floprw08 | Jump if not 2040 2041 moveq.l #1,d3 | Set counter to 1 2042 2042 bra floprw10 2043 * 2044 floprw08: move.w 24(a5),d0 *Get dspt2045 sub.w d4,d0 *Subtract sector number2046 cmp.w 18(a6),d0 *Compare with number of sectors2047 bge floprw09 *Jump if greater than or eq to2048 * 2049 move.w 24(a5),d3 *Get dspt2050 sub.w d4,d3 *Subtract sector number2043 2044 floprw08: move.w 24(a5),d0 | Get dspt 2045 sub.w d4,d0 | Subtract sector number 2046 cmp.w 18(a6),d0 | Compare with number of sectors 2047 bge floprw09 | Jump if greater than or eq to 2048 2049 move.w 24(a5),d3 | Get dspt 2050 sub.w d4,d3 | Subtract sector number 2051 2051 bra floprw10 2052 * 2053 floprw09: move.w 18(a6),d3 *Count = number of sectors2054 * 2055 floprw10: addq.w #1,d4 *Adjust sector number (1 org)2056 * 2057 floprw11: tst.w 8(a6) *Test r/w flag2058 beq floprw14 *Jump if it's a read2059 * 2060 move.l -6(a6),d0 *Get buffer pointer2061 cmp.l 10(a6),d0 *See if it's = buffer addr2062 beq floprw12 *Jump if so2063 * 2064 move.l -6(a6),(a7) *Get source address2065 move.l 10(a6),-(a7) *Destination address2066 jsr fastcopy *Copy the sector2067 addq.l #4,a7 *Cleanup stack2068 * 2069 floprw12: move.w d3,(a7) *Number of sectors2070 move.w d5,-(a7) *Side number2071 move.w d6,-(a7) *Track number2072 move.w d4,-(a7) *Sector number2073 move.w 16(a6),-(a7) *Drive number2074 clr.l -(a7) *Filler2075 move.l -6(a6),-(a7) *Buffer address2076 jsr flopwr *Write sector2077 add.l #16,a7 *Cleaup stack2078 move.l d0,d7 *Save error code in d72079 tst.l d7 *Errors ?2080 bne floprw13 *Jump if so2081 * 2082 .page 2083 * 2084 tst.w fverify *Verify after write ?2085 beq floprw13 *Jump if not2086 * 2087 move.w d3,(a7) *Number of sectors2088 move.w d5,-(a7) *Side number2089 move.w d6,-(a7) *Track number2090 move.w d4,-(a7) *Sector number2091 move.w 16(a6),-(a7) *Drive number2092 clr.l -(a7) *Filler2093 move.l #buffer,-(a7) *Buffer address2094 jsr flopver *Verify sector(s)2095 add.l #16,a7 *Cleanup stack2096 move.l d0,d7 *Save error code in d72097 tst.l d7 *Errors ?2098 bne floprw13 *Jump if so2099 * 2100 move.l #buffer,(a7) *Address of sector buffer2101 bsr itom *Convert first word of buffer2102 tst.w d0 *Bad sectors ?2103 beq floprw13 *Jump if not2104 * 2105 moveq.l #ERR16,d7 *ERROR -- "Bad sectors"2106 * 2052 2053 floprw09: move.w 18(a6),d3 | Count = number of sectors 2054 2055 floprw10: addq.w #1,d4 | Adjust sector number (1 org) 2056 2057 floprw11: 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 2069 floprw12: 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 2107 2107 floprw13: bra floprw15 2108 * 2109 .page 2110 * 2111 floprw14: move.w d3,(a7) *Number of sectors2112 move.w d5,-(a7) *Side number2113 move.w d6,-(a7) *Track number2114 move.w d4,-(a7) *Sector number2115 move.w 16(a6),-(a7) *Drive number2116 clr.l -(a7) *Filler2117 move.l -6(a6),-(a7) *Sector buffer2118 jsr floprd *Read floppy sector(s)2119 add.l #16,a7 *Cleanup stack2120 move.l d0,d7 *Save error code in d72121 move.l -6(a6),d0 *User buffer address2122 cmp.l 10(a6),d0 *Is it the desired buffer ?2123 beq floprw15 *Jump if so2124 * 2125 move.l 10(a6),(a7) *Push source address2126 move.l -6(a6),-(a7) *Push destination address2127 jsr fastcopy *Copy the sector2128 addq.l #4,a7 *Cleanup stack2129 * 2130 floprw15: tst.l d7 *Error code set ?2131 bge floprw16 *Jump if not2132 * 2133 move.w 16(a6),(a7) *Push drive number2134 move.l d7,d0 *Error code2135 move.w d0,-(a7) *... onto stack2136 jsr criter *Call critical error handler2137 addq.l #2,a7 *Cleanup stack2138 move.l d0,d7 *Get error code2139 * 2140 floprw16: cmp.l #RETRYIT,d7 *Re-try ?2141 beq floprw11 *Jump if so2142 * 2143 tst.l d7 *Check error code2144 bge floprw17 *Jump if no error2145 * 2146 move.l d7,d0 *Error code is the result2108 2109 .page 2110 2111 floprw14: 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 2130 floprw15: 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 2140 floprw16: cmp.l #RETRYIT,d7 | Re-try ? 2141 beq floprw11 | Jump if so 2142 2143 tst.l d7 | Check error code 2144 bge floprw17 | Jump if no error 2145 2146 move.l d7,d0 | Error code is the result 2147 2147 bra floprw19 2148 * 2149 .page 2150 * 2151 floprw17: move.w d3,d0 *Sector counter to d02152 ext.l d0 *Sign extend2153 moveq.l #9,d1 *Times 5122154 asl.l d1,d0 *...2155 add.l d0,10(a6) *Update buffer address2156 add.w d3,14(a6) *Update sector number2157 sub.w d3,18(a6) *Update sector count2158 * 2159 floprw18: tst.w 18(a6) *More sectors ?2160 bne floprw03 *Jump if so2161 * 2162 clr.l d0 *Set "no error" as result2163 * 2164 floprw19: tst.l (a7)+ *Test top of stack2165 movem.l (a7)+,d3-d7/a5 *Restore registers2166 unlk a6 *Release stack space2167 rts *Return to caller2168 * 2169 .page 2170 * 2171 *itom -- Convert 8086 integer format to 680000 integer format2172 *---- ----------------------------------------------------2173 itom: link a6,#-4 *Reserve stack for temps2174 move.l 8(a6),a0 *Address of the number to a02175 move.b 1(a0),d0 *Get high byte2176 ext.w d0 *Make it a word2177 and.w # $FF,d0 *Isolate bits 0..72178 asl.w #8,d0 *Shift in bits 8..152179 move.l 8(a6),a1 *Address of the number to a12180 move.b (a1),d1 *Get low byte2181 ext.w d1 *Extend to word2182 and.w # $FF,d1 *Isolate bits 0..72183 or.w d1,d0 *Combine with bits 8..152184 unlk a6 *Release stack space2185 rts *Return to caller2186 * 2187 .page 2188 * 2189 *flopini -- Initialize floppy drive2190 *------- -----------------------2191 flopini: lea dsb0,a1 *Point to dsb for drive A2192 tst.w 12(a7) *Drive A wanted ?2193 beq flopin01 *Jump if so2194 * 2195 lea dsb1,a1 *Drive B dsb address to a12196 * 2197 flopin01: move.w seekrate,2(a1) *Get seek rate2198 moveq.l #ERR01,d0 *Set default error number2199 clr.w 0(a1) *Set track number to 02200 bsr floplock *Setup floppy parameters2201 bsr select *Select drive and side2202 move.w # $FF00,0(a1)2203 bsr restore *Restore the drive2148 2149 .page 2150 2151 floprw17: 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 2159 floprw18: tst.w 18(a6) | More sectors ? 2160 bne floprw03 | Jump if so 2161 2162 clr.l d0 | Set "no error" as result 2163 2164 floprw19: 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 | ---- ---------------------------------------------------- 2173 itom: 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 | ------- ----------------------- 2191 flopini: 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 2197 flopin01: move.w seekrate,2(a1) | Get seek rate 2198 moveq.l #ERR01,d0 | Set default error number 2199 clr.w 0(a1) | Set track number to 0 2200 bsr floplock | Setup floppy parameters 2201 bsr select | Select drive and side 2202 move.w #0xFF00,0(a1) 2203 bsr restore | Restore the drive 2204 2204 moveq.l #6,d7 2205 2205 bsr hseek1 2206 2206 bne flopin02 2207 * 2208 bsr restore *Restore the drive2209 beq flopok *Jump if no error2210 * 2211 flopin02: bra flopfail *Jump to error handler2212 * 2213 .page 2214 * 2215 *floprd -- Read floppy2216 *------ -----------2217 floprd: bsr change *Disk changed ?2218 moveq.l #ERR11,d0 *Set to "read error"2219 bsr floplock *Set parameters2220 * 2221 floprd01: bsr select *Select drive and side2222 bsr go2track *Position on track2223 bne floprd02 *Try again on error2224 * 2225 move.w #ERR01,deferr *Set default error2226 move.l edma(a5),a0 *Get final DMA address2227 move.l cdma(a5),a2 *Get first DMA address2228 move.l # $40000,d7 *Set timeout counter2229 move.b #FL_RM,DSKCMD(a6) *Start readng the disk2230 * 2231 floprd03: btst #0,DSKCMD(a6) *Disk busy yet ?2232 bne floprd05 *Jump if so2233 * 2234 subq.l #1,d7 *Decrement timeout counter2235 beq floprd04 *Jump if timed out2236 * 2237 bra floprd03 *Go try for busy again2238 * 2239 floprd05: move.l # $40000,d7 *Reset timeout counter2240 bra floprd09 *Go join main read loop2241 * 2242 floprd07: subq.l #1,d7 *Decrement timeout counter2243 beq floprd04 *Jump if timed out2244 * 2245 btst #0,DSKCMD(a6) *Done yet ?2246 beq floprd08 *Jump if so2247 * 2248 floprd09: btst #1,DSKCMD(a6) *DRQ set ?2249 beq floprd07 *Jump if not2250 * 2251 move.b DSKDAT(a6),(a2)+ *Read the byte into the buffer2252 cmp.l a0,a2 *Done reading ?2253 bne floprd07 *Jump if not2254 * 2255 .page 2256 * 2257 floprd08: move.b DSKCMD(a6),d0 *Read final status into d02258 and.b # $1C,d0 *Mask for error bits2259 beq flopok *Jump if no errors2260 * 2261 bsr errbits *Determine error code2262 * 2263 floprd02: cmp.w #1,retrycnt(a5) *Re-try ?2264 bne floprd06 *Jump if not2265 * 2266 bsr reseek *Home and repeat the seek2267 * 2268 floprd06: subq.w #1,retrycnt(a5) *Update re-try count2269 bpl floprd01 *Re-try if count still >02270 * 2271 bra flopfail *Failure2272 * 2273 floprd04: move.w #ERR02,curerr(a5) *Set error code "not ready"2274 bsr rs1772 *Reset the WD17722275 bra floprd02 *See if it can be retried2276 * 2277 .page 2278 * 2279 *errbits -- Develop error code for floppy I/O error2280 *------- ---------------------------------------2281 errbits: moveq.l #ERR13,d1 *Write protect ?2282 btst #6,d0 *...2283 bne errbits1 *Jump if so2284 * 2285 moveq.l #ERR08,d1 *Record not found ?2286 btst #4,d0 *...2287 bne errbits1 *Jump if so2288 * 2289 moveq.l #ERR04,d1 *CRC error ?2290 btst #3,d0 *...2291 bne errbits1 *Jump if so2292 * 2293 moveq.l #ERR12,d1 *Lost data ?2294 btst #2,d0 *...2295 bne errbits1 *Jump if so2296 * 2297 move.w deferr(a5),d1 *Use default error2298 * 2299 errbits1: move.w d1,curerr(a5) *... as curerr2300 rts *Return to caller2301 * 2302 .page 2303 * 2304 *flopwr -- Floppy write2305 *------ ------------2306 flopwr: bsr change *Check for disk change2307 moveq.l #ERR10,d0 *Set write error2308 bsr floplock *Set parameters2309 move.w csect(a5),d0 *Get sector number in d02310 subq.w #1,d0 *... -12311 or.w ctrack(a5),d0 *OR with track number2312 or.w cside(a5),d0 *OR with side number2313 bne flopwr01 *Jump if not boot sector2314 * 2315 moveq.l #2,d0 *Media change2316 bsr setdmode *Set to "unsure"2317 * 2318 flopwr01: bsr select *Select drive and side2319 bsr go2track *Seek2320 bne flopwr06 *Re-try on error2321 * 2322 flopwr02: move.w #ERR01,curerr(a5) *Set for default error2323 move.l cdma(a5),a2 *Get I/O address2324 move.l # $40000,d7 *Set timeout counter2325 move.w ctrack(a5),d0 *Get track number2326 cmpi.w #40,d0 *See if we need precomp2327 bcs flopwr10 *Jump if not2328 * 2329 move.b #FL_WS,DSKCMD(a6) *Write with precomp2330 bra flopwr08 *Go join main write loop2331 * 2332 flopwr10: move.b #FL_WS+FL_NC,DSKCMD(a6) *Write (no precomp)2333 * 2334 .page 2335 * 2336 flopwr08: btst #0,DSKCMD(a6) *Busy yet ?2337 bne flopwr09 *Jump if so2338 * 2339 subq.l #1,d7 *Decrement tiemout count2340 bne flopwr08 *Jump if not timed out2341 * 2342 flopwr13: bsr rs1772 *Reset WD17722343 bra flopwr05 *See if we can retry2344 * 2345 flopwr11: btst #0,DSKCMD(a6) *Done ?2346 beq flopwr04 *Jump if so2347 * 2348 flopwr09: btst #1,DSKCMD(a6) *DRQ set ?2349 bne flopwr12 *Jump if so2350 * 2351 subq.l #1,d7 *Decrement timeout counter2352 beq flopwr13 *Jump if timed out2353 * 2354 bra flopwr11 *Jump if not2355 * 2356 flopwr12: move.b (a2)+,DSKDAT(a6) *Write byte to floppy2357 bra flopwr11 *Go get the next one2358 * 2359 .page 2360 * 2361 flopwr04: move.b DSKCMD(a6),d0 *Get floppy status2362 bsr errbits *Set error code2363 btst #6,d0 *Write protect error ?2364 bne flopfail *Fail if so2365 * 2366 and.b # $5C,d0 *Mask error bits2367 bne flopwr05 *Jump if an error occurred2368 * 2369 addq.w #1,csect(a5) *Update sector number2370 add.l #512,cdma(a5) *Update DMA address2371 subq.w #1,ccount(a5) *Decrement sector count2372 beq flopok *Jump if zero -- done2373 * 2374 bsr select1 *Set sector and DMA pointer2375 bra flopwr02 *Write next sector2376 * 2377 flopwr05: cmp.w #1,retrycnt(a5) *Second re-try ?2378 bne flopwr07 *Jump if not2379 * 2380 flopwr06: bsr reseek *Restore and re-seek2381 * 2382 flopwr07: subq.w #1,retrycnt(a5) *Update re-try count2383 bpl flopwr01 *Re-try if still >02384 * 2385 bra flopfail *... else fail2386 * 2387 .page 2388 * 2389 *flopfmt -- Format a track on the floppy2390 *------- ----------------------------2391 flopfmt: cmp.l #FMAGIC,22(a7) *Is the magic right ?2392 bne flopfail *Fail immediately if not2393 * 2394 bsr change *Check for disk change2395 moveq.l #ERR01,d0 *Set default error number2396 bsr floplock *Set parameters2397 bsr select *Select drive and side2398 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 changed2402 bsr setdmode *...2403 bsr hseek *Seek2404 bne flopfail *Fail if seek error occurs2405 * 2406 move.w ctrack(a5),0(a1) *Current track to DSB2407 move.w #ERR01,curerr(a5) *Default to curerr2408 bsr fmtrack *Format the track2409 bne flopfail *Fail if error occurs2410 * 2411 move.w spt(a5),ccount(a5) *Use spt as ccount2412 move.w #1,csect(a5) *Start with sector 12413 bsr verify1 *Verify the sector2414 move.l cdma(a5),a2 *Get bad sector list2415 tst.w (a2) *Any bad ones ?2416 beq flopok *Jump if not2417 * 2418 move.w #ERR16,curerr(a5) *ERROR -- "bad sectors"2207 2208 bsr restore | Restore the drive 2209 beq flopok | Jump if no error 2210 2211 flopin02: bra flopfail | Jump to error handler 2212 2213 .page 2214 2215 | floprd -- Read floppy 2216 | ------ ----------- 2217 floprd: bsr change | Disk changed ? 2218 moveq.l #ERR11,d0 | Set to "read error" 2219 bsr floplock | Set parameters 2220 2221 floprd01: 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 2231 floprd03: 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 2239 floprd05: move.l #0x40000,d7 | Reset timeout counter 2240 bra floprd09 | Go join main read loop 2241 2242 floprd07: 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 2248 floprd09: 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 2257 floprd08: 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 2263 floprd02: cmp.w #1,retrycnt(a5) | Re-try ? 2264 bne floprd06 | Jump if not 2265 2266 bsr reseek | Home and repeat the seek 2267 2268 floprd06: subq.w #1,retrycnt(a5) | Update re-try count 2269 bpl floprd01 | Re-try if count still >0 2270 2271 bra flopfail | Failure 2272 2273 floprd04: 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 | ------- --------------------------------------- 2281 errbits: 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 2299 errbits1: move.w d1,curerr(a5) | ... as curerr 2300 rts | Return to caller 2301 2302 .page 2303 2304 | flopwr -- Floppy write 2305 | ------ ------------ 2306 flopwr: 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 2318 flopwr01: bsr select | Select drive and side 2319 bsr go2track | Seek 2320 bne flopwr06 | Re-try on error 2321 2322 flopwr02: 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 2332 flopwr10: move.b #FL_WS+FL_NC,DSKCMD(a6) | Write (no precomp) 2333 2334 .page 2335 2336 flopwr08: 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 2342 flopwr13: bsr rs1772 | Reset WD1772 2343 bra flopwr05 | See if we can retry 2344 2345 flopwr11: btst #0,DSKCMD(a6) | Done ? 2346 beq flopwr04 | Jump if so 2347 2348 flopwr09: 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 2356 flopwr12: move.b (a2)+,DSKDAT(a6) | Write byte to floppy 2357 bra flopwr11 | Go get the next one 2358 2359 .page 2360 2361 flopwr04: 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 2377 flopwr05: cmp.w #1,retrycnt(a5) | Second re-try ? 2378 bne flopwr07 | Jump if not 2379 2380 flopwr06: bsr reseek | Restore and re-seek 2381 2382 flopwr07: 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 | ------- ---------------------------- 2391 flopfmt: cmp.l #FMAGIC,22(a7) | Is the magic right ? 2392 bne flopfail | Fail immediately if not 2393 2394 bsr change | Check for disk change 2395 moveq.l #ERR01,d0 | Set default error number 2396 bsr floplock | Set parameters 2397 bsr select | Select drive and side 2398 move.w 14(a7),spt(a5) | Set sectors per track, 2399 move.w 20(a7),interlv(a5) | ... interleave, 2400 move.w 26(a7),virgin(a5) | ... initial data, 2401 moveq.l #2,d0 | Disk changed 2402 bsr setdmode | ... 2403 bsr hseek | Seek 2404 bne flopfail | Fail if seek error occurs 2405 2406 move.w ctrack(a5),0(a1) | Current track to DSB 2407 move.w #ERR01,curerr(a5) | Default to curerr 2408 bsr fmtrack | Format the track 2409 bne flopfail | Fail if error occurs 2410 2411 move.w spt(a5),ccount(a5) | Use spt as ccount 2412 move.w #1,csect(a5) | Start with sector 1 2413 bsr verify1 | Verify the sector 2414 move.l cdma(a5),a2 | Get bad sector list 2415 tst.w (a2) | Any bad ones ? 2416 beq flopok | Jump if not 2417 2418 move.w #ERR16,curerr(a5) | ERROR -- "bad sectors" 2419 2419 bra flopfail 2420 * 2421 .page 2422 * 2423 *fmtrack -- Do the dirty work of formatting a track2424 *------- ---------------------------------------2425 fmtrack: move.w #ERR10,deferr(a5) *Set default error number2426 move.w #1,d3 *Start with sector 12427 move.l cdma(a5),a2 *Get track buffer address2428 move.w #60-1,d1 *Set count = 602429 move.b # $4E,d0 * Write $4E as initial gap2430 bsr wmult *...2431 * 2432 fmtrak01: move.w d3,d4 *Save sector number in d42433 * 2434 fmtrak02: move.w #12-1,d1 *Set count = 122435 clr.b d0 * Write $00 as sync2436 bsr wmult *...2437 move.w #3-1,d1 *Set count = 32438 move.b # $F5,d0 * Write $F5's2439 bsr wmult *...2440 move.b # $FE,(a2)+ * Write $FE (address mark)2441 move.b ctrack+1,(a2)+ *Write track #2442 move.b cside+1,(a2)+ *Write side #2443 move.b d4,(a2)+ *Write sector #2444 move.b #2,(a2)+ *Write sector size code2445 move.b # $F7,(a2)+ *Write checksum code2446 move.w #22-1,d1 *Set count = 222447 move.b # $4E,d0 *Write gap2448 bsr wmult *...2449 move.w #12-1,d1 *Set count = 122450 clr.b d0 * Write $00 as sync2451 bsr wmult *...2452 move.w #3-1,d1 *Set count = 32453 move.b # $F5,d0 * Write $F5's2454 bsr wmult *...2455 move.b # $FB,(a2)+ *Write DAM2456 move.w #256-1,d1 *Set count = 256 words2457 * 2458 .page 2459 * 2460 fmtrak03: move.b virgin(a5),(a2)+ *Write virgin data in buffer2461 move.b virgin+1(a5),(a2)+ *...2462 dbf d1,fmtrak03 *...2463 * 2464 move.b # $F7,(a2)+ *Write CRC code2465 move.w #40-1,d1 *Set count = 402466 move.b # $4E,d0 *Write gap2467 bsr wmult *...2468 add.w interlv(a5),d4 *Add interleave to sector #2469 cmp.w spt(a5),d4 *Check against spt2470 ble fmtrak02 *Jump if not >2471 * 2472 addq.w #1,d3 *Starting sector +12420 2421 .page 2422 2423 | fmtrack -- Do the dirty work of formatting a track 2424 | ------- --------------------------------------- 2425 fmtrack: 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 2432 fmtrak01: move.w d3,d4 | Save sector number in d4 2433 2434 fmtrak02: 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 2460 fmtrak03: move.b virgin(a5),(a2)+ | Write virgin data in buffer 2461 move.b virgin+1(a5),(a2)+ | ... 2462 dbf d1,fmtrak03 | ... 2463 2464 move.b #0xF7,(a2)+ | Write CRC code 2465 move.w #40-1,d1 | Set count = 40 2466 move.b #0x4E,d0 | Write gap 2467 bsr wmult | ... 2468 add.w interlv(a5),d4 | Add interleave to sector # 2469 cmp.w spt(a5),d4 | Check against spt 2470 ble fmtrak02 | Jump if not > 2471 2472 addq.w #1,d3 | Starting sector +1 2473 2473 cmp.w interlv(a5),d3 2474 2474 ble fmtrak01 2475 * 2476 move.w #1401-1,d1 *Set count = 14012477 move.b # $4E,d0 *Write final gap2478 bsr wmult *...2479 move.l cdma(a5),a2 *Get buffer address2480 move.l # $40000,d7 *Set timeout count2481 move.w ctrack(a5),d0 *Get track number2482 cmpi.w #40,d0 *Do we need precomp ?2483 bcs fmtrak08 *Jump if not2484 * 2485 move.b #FL_WT,DSKCMD(a6) *Start format with precomp2486 bra fmtrak07 *Go join main format loop2487 * 2488 fmtrak08: move.b #FL_WT+FL_NC,DSKCMD(a6) *Start format without precomp2489 * 2490 .page 2491 * 2492 fmtrak07: btst #0,DSKCMD(a6) *Busy yet ?2493 bne fmtrak09 *Jump if so2494 * 2495 fmtrak04: subq.l #1,d7 *Decrement timeout counter2496 bne fmtrak07 *Jump if not timed out2497 * 2498 fmtrak05: bsr rs1772 *Reset WD17722499 moveq.l #1,d7 *Set error flag2500 rts *Return to caller2501 * 2502 fmtrak11: btst #0,DSKCMD(a6) *Done ?2503 beq fmtrak06 *Jump if so2504 * 2505 fmtrak09: btst #1,DSKCMD(a6) *DRQ set ?2506 bne fmtrak10 *Jump if so2507 * 2508 subq.l #1,d7 *Decrement timeout coutner2509 beq fmtrak05 *Jump if timed out2510 * 2511 bra fmtrak11 *Go check again2512 * 2513 fmtrak10: move.b (a2)+,DSKDAT(a6) *Write a byte of format2514 bra fmtrak11 *Go wait for DRQ2515 * 2516 fmtrak06: move.b DSKCMD(a6),d0 *Get final status2517 bsr errbits *Set possible error code2518 andi.b # $44,d0 *Check error bits2519 rts *Return to caller with status2520 * 2521 *wmult -- write multiple bytes into the track buffer2522 *----- ------------------------------------------2523 wmult: move.b d0,(a2)+ *Move a byte into the buffer2524 dbf d1,wmult *Loop until we're done2525 * 2526 rts *Return to caller2527 * 2528 .page 2529 * 2530 *flopver -- verify sector(s) on a floppy2531 *------- ----------------------------2532 flopver: bsr change *Check for disk change2533 moveq.l #ERR11,d0 *Set default to "read error"2534 bsr floplock *Set parameters2535 bsr select *Select drive and side2536 bsr go2track *Seek2537 bne flopfail *Jump if seek error2538 * 2539 bsr verify1 *Verify the data2540 bra flopok *Done2541 * 2542 *verify1 -- Verify the data for a sector2543 *------- ----------------------------2544 verify1: move.w #ERR11,deferr(a5) *Set default = "read error"2545 move.l cdma(a5),a2 *Pointer for bad sector list2546 add.l #512,cdma(a5) *Update by length of a sector2547 * 2548 verify01: move.w #2,retrycnt(a5) *Set retrycnt for 2 attempts2549 move.w csect(a5),d7 *Get sector nubmer2550 move.b d7,DSKSEC(a6) *Send to WD17722551 * 2552 verify02: moveq.l #0,d6 *Clear bad compare flag2553 move.l cdma(a5),a0 *Get compare address2554 move.l # $40000,d7 *Set timeout counter2555 move.b #FL_RS,DSKCMD(a6) *Start the read2556 * 2557 verify08: btst #0,DSKCMD(a6) *Busy yet ?2558 bne verify09 *Jump if so2559 * 2560 subq.l #1,d7 *Decrement timeout counter2561 beq verify13 *Jump if timed out2562 * 2563 bra verify08 *Wait for busy some more2564 * 2565 verify09: move.l # $40000,d7 *Reset timeout counter2566 bra verify11 *Go join main compare loop2567 * 2568 verify10: subq.l #1,d7 *Decrement timeout counter2569 beq verify13 *Jump if timed out2570 * 2571 btst #0,DSKCMD(a6) *Done yet ?2572 beq verify12 *Jump if so2573 * 2574 .page 2575 * 2576 verify11: btst #1,DSKCMD(a6) *DRQ set ?2577 beq verify10 *Jump if not2578 * 2579 move.b DSKDAT(a6),d0 *Read data2580 bra verify10 *Continue reading2581 * 2582 verify12: move.b DSKCMD(a6),d0 *Get final status2583 bsr errbits *Determine error code2584 and.b # $1C,d0 *Mask RNF, CRC, LOST2585 bne verify06 *Jump to re-try if any set2586 * 2587 verify05: addq.w #1,csect(a5) *Update sector number2588 subq.w #1,ccount(a5) *Update sector count2589 bne verify01 *Jump if more to do2590 * 2591 sub.l #512,cdma(a5) *Reset DMA pointer2592 clr.w (a2) *Set NIL in bad sector list2593 rts *Return to caller2594 * 2595 verify06: cmp.w #1,retrycnt(a5) *Is it the 2nd attempt ?2596 bne verify07 *Jump if not2597 * 2598 bsr reseek *Restore and re-seek2599 * 2600 verify07: subq.w #1,retrycnt(a5) *Decrement retry count2601 bpl verify02 *Re-try if still positive2602 * 2603 move.w csect(a5),(a2)+ *Add to bad sector list2604 bra verify05 *Go do next sector2605 * 2606 verify13: move.w #ERR02,curerr(a5) *Set timeout error code2607 bsr rs1772 *Reset WD17722608 bra verify06 *See if we can retry it2609 * 2610 .page 2611 * 2612 *flopvbl -- Floppy VBL timer interrupt handling2613 *------- -----------------------------------2614 flopvbl: movem.l d0-d1/a0-a1/a5-a6,-(a7) *Save registers2615 sub.l a5,a5 *Clear a5 for use as RAM base2616 lea FLOPPY,a6 *Base of floppy regs2617 st motoron(a5) *Set motoron flag2618 move.l frclock(a5),d0 *Get interrupt count2619 move.b d0,d1 *...2620 and.b #7,d1 *... MOD 82621 bne flopvb02 *Jump if not 8th int2622 * 2623 move.w sr,-(a7) *Save interrupt level2624 ori.w #IPL7,sr *Mask off interrupts2625 clr.w deslflag(a5) *Clear deselect flag2626 move.b mc1iorec+cfr1,d0 *Get port status2627 ori.b #1,d0 *Set drive select bit2628 move.b d0,MC1ACIA+ACIA_CFR *Send drive select to port2629 move.b d0,mc1iorec+cfr1 *Store updated port status2630 move.w (a7)+,sr *Restore interrupt level2631 lea wpstatus(a5),a0 *Point at wpstatus for drive2632 lea dsb0(a5),a1 *Point at dsb02633 move.b DSKCMD(a6),d0 *Read WD1772 status2634 btst #6,d0 *Test write protect bit2635 sne (a0) *... and save2636 * 2637 .page 2638 * 2639 flopvb02: move.w wpstatus(a5),d0 *Get wpstatus of drive A2640 or.w d0,wplatch(a5) *OR into wplatch2641 tst.w deslflag(a5) *Floppies already deselected ?2642 bne flopvb03 *Jump if so2643 * 2644 move.b DSKCMD(a6),d0 *Read WD1772 status2645 btst #7,d0 *Motor-on bit set ?2646 bne flopvb04 *Don't de-select if it is2647 * 2648 move.w sr,-(a7) *Save sr2649 ori.w #IPL7,sr *Disable interrupts2650 move.b mc1iorec+cfr1,d0 *Get cfr1 image2651 bclr #0,d0 *Clear d0 (drive select)2652 move.b d0,mc1iorec+cfr1 *Save new value2653 move.b d0,MC1ACIA+ACIA_CFR *Send to hardware2654 move.w (a7)+,sr *Restore sr (enable ints)2655 move.w #1,deslflag(a5) *Set the deselect flag2656 * 2657 flopvb03: clr.w motoron(a5) *Clear motoron flag2658 * 2659 flopvb04: movem.l (a7)+,d0-d1/a0-a1/a5-a6 *Restore registers2660 rts *Return to caller2661 * 2662 .page 2663 * 2664 *floplock -- Setup floppy parameters2665 *-------- -----------------------2666 floplock: movem.l d3-d7/a3-a6,flpregs *Save registers2667 move.w sr,flpsrsv *Save sr2668 ori.w #IPL7,sr *Disable ints2669 sub.l a5,a5 *Clear a52670 lea FLOPPY,a6 *Base of floppy registers2671 st motoron(a5) *Set motoron flag2672 move.w d0,deferr(a5) *Set default error code2673 move.w d0,curerr(a5) *... current error code2674 move.w #1,flock(a5) *Disable flopvbl routine2675 move.l 8(a7),cdma(a5) *Set cdma2676 move.w 16(a7),cdev(a5) *... cdev2677 move.w 18(a7),csect(a5) *... csect2678 move.w 20(a7),ctrack(a5) *... ctrack2679 move.w 22(a7),cside(a5) *... cside2680 move.w 24(a7),ccount(a5) *... ccount2681 move.w #2,retrycnt(a5) *... retrycnt2682 lea dsb0(a5),a1 *Address of dsb02683 tst.w cdev(a5) *Drive A ?2684 beq floplk01 *Jump if so2685 * 2686 lea dsb1(a5),a1 *Drive B, use dsb12687 * 2688 floplk01: moveq.l #0,d7 *Clear out d72689 move.w ccount(a5),d7 *Get ccount2690 lsl.w #8,d7 * ... *sector length (512)2691 lsl.w #1,d7 *...2692 move.l cdma(a5),a0 *Get DMA start address2693 add.l d7,a0 *Add length of sectors2694 move.l a0,edma(a5) *Set edma (end DMA address)2695 tst.w 0(a1) *Check current track2696 bpl floplk03 *Jump if >= 02697 * 2698 bsr select *Select the drive2699 clr.w 0(a1) *Set current track to 02700 bsr restore *Restore drive to track 02701 beq floplk03 *Jump if OK2702 * 2703 moveq.l #10,d7 *Seek out to track 102704 bsr hseek1 *...2705 bne floplk02 *Jump if an error occurred2706 * 2707 bsr restore *Try the restore again2708 beq floplk03 *Jump if OK2709 * 2710 floplk02: move.w # $FF00,0(a1) *Recalibrate error2711 * 2712 floplk03: rts *Return to caller2713 * 2714 .page 2715 * 2716 *flopfail -- Floppy I/O failure exit2717 *-------- -----------------------2718 flopfail: moveq.l #1,d0 *Set media change to "unsure"2719 bsr setdmode *...2720 move.w curerr(a5),d0 *Get curerr2721 ext.l d0 *...2722 bra flopok1 *Go set end status2723 * 2724 *flopok -- Floppy I/O success exit2725 *------ -----------------------2726 flopok: clr.l d0 *Set error code = 0 (no error)2727 * 2728 flopok1: move.l d0,-(a7) *Push code onto stack2729 move.w 0(a1),d7 *Get track number2730 move.b d7,DSKDAT(a6) *Send to WD17722731 move.w #FL_SK,d6 *Seek command to d62732 bsr flopcmds *Send command2733 move.w cdev(a5),d0 *Get drive number2734 lsl.w #2,d0 *Use as index2735 lea acctim(a5),a0 *... into acctim2736 move.l _hz_200(a5),0(a0,d0) *Set last access time2475 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 2488 fmtrak08: move.b #FL_WT+FL_NC,DSKCMD(a6) | Start format without precomp 2489 2490 .page 2491 2492 fmtrak07: btst #0,DSKCMD(a6) | Busy yet ? 2493 bne fmtrak09 | Jump if so 2494 2495 fmtrak04: subq.l #1,d7 | Decrement timeout counter 2496 bne fmtrak07 | Jump if not timed out 2497 2498 fmtrak05: bsr rs1772 | Reset WD1772 2499 moveq.l #1,d7 | Set error flag 2500 rts | Return to caller 2501 2502 fmtrak11: btst #0,DSKCMD(a6) | Done ? 2503 beq fmtrak06 | Jump if so 2504 2505 fmtrak09: 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 2513 fmtrak10: move.b (a2)+,DSKDAT(a6) | Write a byte of format 2514 bra fmtrak11 | Go wait for DRQ 2515 2516 fmtrak06: 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 | ----- ------------------------------------------ 2523 wmult: 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 | ------- ---------------------------- 2532 flopver: 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 | ------- ---------------------------- 2544 verify1: 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 2548 verify01: 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 2552 verify02: 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 2557 verify08: 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 2565 verify09: move.l #0x40000,d7 | Reset timeout counter 2566 bra verify11 | Go join main compare loop 2567 2568 verify10: 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 2576 verify11: 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 2582 verify12: 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 2587 verify05: 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 2595 verify06: 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 2600 verify07: 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 2606 verify13: 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 | ------- ----------------------------------- 2614 flopvbl: 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 2639 flopvb02: 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 2657 flopvb03: clr.w motoron(a5) | Clear motoron flag 2658 2659 flopvb04: 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 | -------- ----------------------- 2666 floplock: 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 2688 floplk01: moveq.l #0,d7 | Clear out d7 2689 move.w ccount(a5),d7 | Get ccount 2690 lsl.w #8,d7 | ... | sector length (512) 2691 lsl.w #1,d7 | ... 2692 move.l cdma(a5),a0 | Get DMA start address 2693 add.l d7,a0 | Add length of sectors 2694 move.l a0,edma(a5) | Set edma (end DMA address) 2695 tst.w 0(a1) | Check current track 2696 bpl floplk03 | Jump if >= 0 2697 2698 bsr select | Select the drive 2699 clr.w 0(a1) | Set current track to 0 2700 bsr restore | Restore drive to track 0 2701 beq floplk03 | Jump if OK 2702 2703 moveq.l #10,d7 | Seek out to track 10 2704 bsr hseek1 | ... 2705 bne floplk02 | Jump if an error occurred 2706 2707 bsr restore | Try the restore again 2708 beq floplk03 | Jump if OK 2709 2710 floplk02: move.w #0xFF00,0(a1) | Recalibrate error 2711 2712 floplk03: rts | Return to caller 2713 2714 .page 2715 2716 | flopfail -- Floppy I/O failure exit 2717 | -------- ----------------------- 2718 flopfail: 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 | ------ ----------------------- 2726 flopok: clr.l d0 | Set error code = 0 (no error) 2727 2728 flopok1: move.l d0,-(a7) | Push code onto stack 2729 move.w 0(a1),d7 | Get track number 2730 move.b d7,DSKDAT(a6) | Send to WD1772 2731 move.w #FL_SK,d6 | Seek command to d6 2732 bsr flopcmds | Send command 2733 move.w cdev(a5),d0 | Get drive number 2734 lsl.w #2,d0 | Use as index 2735 lea acctim(a5),a0 | ... into acctim 2736 move.l _hz_200(a5),0(a0,d0) | Set last access time 2737 2737 cmp.w #1,nflops(a5) 2738 2738 bne flopok01 2739 * 2740 move.l _hz_200(a5),4(a0) *Time for other drive2741 * 2742 flopok01: move.w flpsrsv,sr *Restore sr (enable ints)2743 move.l (a7)+,d0 *Restore error number to d02744 movem.l flpregs,d3-d7/a3-a6 *Restore registers2745 clr.w flock *Release flopvbl routine2746 rts *Return to caller2747 * 2748 .page 2749 * 2750 *hseek -- seek to track in ctrack2751 *----- -----------------------2752 hseek: move.w ctrack,d7 *Get ctrack2753 * 2754 *hseek1 -- seek to track in d72755 *------ -------------------2756 hseek1: move.w #ERR10,curerr *Set curerr = "seek error"2757 move.b d7,DSKDAT(a6) *Send track number to WD17722758 move.w #FL_SK,d6 *Seek command2759 bra flopcmds *Go send command to WD17722760 * 2761 *reseek -- Restore, then re-seek2762 *------ ---------------------2763 reseek: move.w #ERR10,curerr *Set curerr = "seek error"2764 bsr restore *Restore2765 bne reseek01 *Jump if error occurred2766 * 2767 clr.w 0(a1) *Clear current track to 02768 move.b #0,DSKTRK(a6) *Send track to WD17722769 move.b #5,DSKDAT(a6) *Setup to seek to track 52770 move.w #FL_SK,d6 *Seek command2771 bsr flopcmds *Seek2772 bne reseek01 *Jump if error2773 * 2774 move.w #5,0(a1) *Update current track = 52775 * 2776 *go2track -- seek with verify2777 *-------- ----------------2778 go2track: move.w #ERR10,curerr(a5) *Set curerr = "seek error"2779 move.w ctrack(a5),d7 *Put track # in d72780 move.b d7,DSKDAT(a6) *Send track to WD17722781 moveq.l #FL_SV,d6 *Seek/verify command2782 bsr flopcmds *Send command to floppy2783 bne reseek01 *Jump if error occurred2784 * 2785 move.w ctrack(a5),0(a1) *Update track number in dsb2786 and.b # $18,d7 *Test for RNF, CRC, LOST2787 * 2788 reseek01: rts *Return to caller2789 * 2790 .page 2791 * 2792 *restore -- Restore to track 02793 *------- ------------------2794 restore: clr.w d6 *Restore command2795 bsr flopcmds *Send to WD17722796 bne restor01 *Jump if an error occurred2797 * 2798 btst #2,d7 *Check track 0 bit2799 eori #0004,sr *Invert Z flag in 680000 sr2800 bne restor01 *Jump if not track 02801 * 2802 clr.w 0(a1) *Set track = 0 in dsb2803 * 2804 restor01: rts *Return to caller2805 * 2806 *flopcmds -- Send command to WD1772 floppy controller2807 *-------- ----------------------------------------2808 flopcmds: move.w 2(a1),d0 *Get seek rate from dsb2809 and.b # $3,d0 *...2810 or.b d0,d6 *OR into command word2811 move.l # $40000,d7 *Set timeout counter2812 btst #7,DSKCMD(a6) *Motor on ?2813 bne flopcm01 *Jump if so2814 * 2815 move.l # $60000,d7 *Set longer timeout count2816 * 2817 flopcm01: move.b d6,DSKCMD(a6) *Write command from d62818 * 2819 move.l # $1000,d0 *Set initial busy timeout in d02820 * 2821 flopcm04: btst #0,DSKCMD(a6) *Controller busy yet ?2822 bne flopcm02 *Jump if so2823 * 2824 subq.l #1,d0 *Decrement timeout counter2825 beq flopcm03 *Jump if timed out2826 * 2827 bra flopcm04 *Wait for busy some more2828 * 2829 flopcm02: subq.l #1,d7 *Decrement timeout counter2830 beq flopcm03 *Jump if timed out2831 * 2832 btst #0,DSKCMD(a6) *WD1772 done ?2833 bne flopcm02 *Jump if not2834 * 2835 clr.l d7 *Clear out upper bits of d72836 move.b DSKCMD(a6),d7 *Read status into LS byte of d72837 clr.l d6 *Clear error flag in d62838 rts *Return to caller2839 * 2840 flopcm03: bsr rs1772 *Reset WD1772 (end transfer)2841 moveq.l #1,d6 *Set error flag in d62842 rts *Return to caller2843 * 2844 .page 2845 * 2846 *rs1772 -- Reset WD1772 floppy controller2847 *------ ------------------------------2848 rs1772: move.b #FL_FR,DSKCMD(a6) *Send reset to WD17722849 move.w #15,d7 *Set delay count2850 * 2851 rs1772a: dbf d7,rs1772a *Delay a while2852 rts *Return to caller2853 * 2854 *select -- Select drive and side2855 *------ ----------------------2856 select: move.w sr,-(a7) *Save sr on stack2857 ori.w #IPL7,sr *Disable interrupts2858 clr.w deslflag(a5) *Clear deselect flag2859 move.b mc1iorec+cfr1,d0 *Get current MC1 cfr1 image2860 ori.b #1,d0 *Select drive (we only have 1)2861 move.b d0,mc1iorec+cfr1 *Store updated image2862 move.b d0,MC1ACIA+ACIA_CFR *Send it to the MC1 ACIA2863 move.w cside(a5),d0 *Get side number (LS bit)2864 and.w #1,d0 *Mask off garbage bits2865 andi.b # $FE,mc2iorec+cfr1 *Mask off D0 in MC2 cfr1 image2866 or.b mc2iorec+cfr1,d0 *OR side with mc2iorec cfr12867 move.b d0,mc2iorec+cfr1 *Store updated cfr1 image2868 move.b d0,MC2ACIA+ACIA_CFR *Send it to the MC2 ACIA2869 move.w (a7)+,sr *Restore interrupts2870 move.w 0(a1),d7 *Get track from dsb2871 move.b d7,DSKTRK(a6) *Send it to the WD17722872 clr.b tmpdma(a5) *Clear bits 31..24 of tmpdma2873 * 2874 select1: move.w csect(a5),d7 *Get sector number2875 move.b d7,DSKSEC(a6) *Send it to the WD17722876 move.l cdma(a5),a0 *Setup transfer address in a02877 rts *Return to caller2878 * 2879 .page 2880 * 2881 *change -- Check for disk change status2882 *------ ----------------------------2883 change: cmp.w #1,nflops *Check # of floppies2739 2740 move.l _hz_200(a5),4(a0) | Time for other drive 2741 2742 flopok01: 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 | ----- ----------------------- 2752 hseek: move.w ctrack,d7 | Get ctrack 2753 2754 | hseek1 -- seek to track in d7 2755 | ------ ------------------- 2756 hseek1: 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 | ------ --------------------- 2763 reseek: 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 | -------- ---------------- 2778 go2track: 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 2788 reseek01: rts | Return to caller 2789 2790 .page 2791 2792 | restore -- Restore to track 0 2793 | ------- ------------------ 2794 restore: 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 2804 restor01: rts | Return to caller 2805 2806 | flopcmds -- Send command to WD1772 floppy controller 2807 | -------- ---------------------------------------- 2808 flopcmds: 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 2817 flopcm01: move.b d6,DSKCMD(a6) | Write command from d6 2818 2819 move.l #0x1000,d0 | Set initial busy timeout in d0 2820 2821 flopcm04: 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 2829 flopcm02: 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 2840 flopcm03: 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 | ------ ------------------------------ 2848 rs1772: move.b #FL_FR,DSKCMD(a6) | Send reset to WD1772 2849 move.w #15,d7 | Set delay count 2850 2851 rs1772a: dbf d7,rs1772a | Delay a while 2852 rts | Return to caller 2853 2854 | select -- Select drive and side 2855 | ------ ---------------------- 2856 select: 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 2874 select1: 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 | ------ ---------------------------- 2883 change: cmp.w #1,nflops | Check # of floppies 2884 2884 bne change02 2885 * 2886 move.w 16(a7),d0 *Drive number to d02885 2886 move.w 16(a7),d0 | Drive number to d0 2887 2887 cmp.w disknum,d0 2888 beq change01 *Jump if =2889 * 2890 move.w d0,-(a7) *Stack drive number2891 move.w #ERR17,-(a7) *Stack error code2892 bsr criter *Do critical error routine2893 addq.w #4,a7 *Cleanup stack2894 move.w # $FFFF,wplatch *Status for drives = "unsure"2895 move.w 16(a7),disknum *Save disk number2896 * 2897 change01: clr.w 16(a7) *Clear disk number2898 * 2899 change02: rts *Return to caller2900 * 2901 *setdmode -- Set drive change mode2902 *-------- ---------------------2903 setdmode: lea dskmode,a0 *Point at disk mode table2904 move.b d0,-(a7) *Save mode on stack2905 move.w cdev(a5),d0 *Get drive number2906 move.b (a7)+,0(a0,d0) *Set drive mode / cleanup stack2907 rts *Return to caller2908 * 2909 .page 2910 * 2911 *bootload -- Load boot sector2912 *-------- ----------------2913 bootload: link a6,#0 *Link stack frames2914 movem.l d6-d7,-(a7) *Save registers2915 jsr _hdvini *Init drive2916 tst.w nflops *See if any connected2917 beq bootld01 *Jump if drive there2918 * 2919 moveq.l #1,d0 *"couldn't load"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 2897 change01: clr.w 16(a7) | Clear disk number 2898 2899 change02: rts | Return to caller 2900 2901 | setdmode -- Set drive change mode 2902 | -------- --------------------- 2903 setdmode: 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 | -------- ---------------- 2913 bootload: link a6,#0 | Link stack frames 2914 movem.l d6-d7,-(a7) | Save registers 2915 jsr _hdvini | Init drive 2916 tst.w nflops | See if any connected 2917 beq bootld01 | Jump if drive there 2918 2919 moveq.l #1,d0 | "couldn't load" 2920 2920 bra bootld02 2921 * 2922 bootld01: moveq.l #2,d0 *"no drive connected"2923 * 2924 bootld02: move.w d0,d7 *Save possible error in d72921 2922 bootld01: moveq.l #2,d0 | "no drive connected" 2923 2924 bootld02: move.w d0,d7 | Save possible error in d7 2925 2925 tst.w nflops 2926 2926 beq bootld04 2927 * 2927 2928 2928 cmp.w #2,bootdev 2929 2929 bge bootld04 2930 * 2931 move.w #1,(a7) *Sector count = 1,2932 clr.w -(a7) *... side = 0,2933 clr.w -(a7) *... track = 0,2934 move.w #1,-(a7) *... sector = 1,2935 move.w bootdev,-(a7) *... drive = bootdev,2936 clr.l -(a7) *... filler,2937 move.l #buffer,-(a7) *... buffer address2938 jsr floprd *Read the sector2939 add.l #16,a7 *Cleanup stack2940 tst.l d0 *Error ?2941 bne bootld03 *Jump if not2942 * 2930 2931 move.w #1,(a7) | Sector count = 1, 2932 clr.w -(a7) | ... side = 0, 2933 clr.w -(a7) | ... track = 0, 2934 move.w #1,-(a7) | ... sector = 1, 2935 move.w bootdev,-(a7) | ... drive = bootdev, 2936 clr.l -(a7) | ... filler, 2937 move.l #buffer,-(a7) | ... buffer address 2938 jsr floprd | Read the sector 2939 add.l #16,a7 | Cleanup stack 2940 tst.l d0 | Error ? 2941 bne bootld03 | Jump if not 2942 2943 2943 clr.w d7 2944 2944 bra bootld04 2945 * 2945 2946 2946 bootld03: tst.b wpstatus 2947 2947 bne bootld04 2948 * 2949 moveq.l #3,d0 *"unreadable"2948 2949 moveq.l #3,d0 | "unreadable" 2950 2950 bra bootld07 2951 * 2951 2952 2952 bootld04: tst.w d7 2953 2953 beq bootld05 2954 * 2955 move.w d7,d0 *Get old error code2954 2955 move.w d7,d0 | Get old error code 2956 2956 bra bootld07 2957 * 2958 .page 2959 * 2960 bootld05: move.w #256,(a7) *Set count for 256 words2961 move.l #buffer,-(a7) *Point at buffer2962 bsr chksum *Calculate checksum2963 addq.l #4,a7 *Cleanup stack2964 cmp.w # $1234,d0 *Boot sector checksum ?2965 bne bootld06 *Jump if not2966 * 2967 clr.w d0 *Set flag for OK2968 move.w bootdev,booted *Save last boot device2957 2958 .page 2959 2960 bootld05: move.w #256,(a7) | Set count for 256 words 2961 move.l #buffer,-(a7) | Point at buffer 2962 bsr chksum | Calculate checksum 2963 addq.l #4,a7 | Cleanup stack 2964 cmp.w #0x1234,d0 | Boot sector checksum ? 2965 bne bootld06 | Jump if not 2966 2967 clr.w d0 | Set flag for OK 2968 move.w bootdev,booted | Save last boot device 2969 2969 bra bootld07 2970 * 2971 bootld06: moveq.l #4,d0 *"not valid boot sector"2972 * 2970 2971 bootld06: moveq.l #4,d0 | "not valid boot sector" 2972 2973 2973 bootld07: tst.l (a7)+ 2974 movem.l (a7)+,d7 *Restore registers2974 movem.l (a7)+,d7 | Restore registers 2975 2975 unlk a6 2976 rts *Return to caller2977 * 2978 .page 2979 * 2980 *chksum -- caluculate checksum2981 *------ -------------------2976 rts | Return to caller 2977 2978 .page 2979 2980 | chksum -- caluculate checksum 2981 | ------ ------------------- 2982 2982 chksum: link a6,#0 2983 movem.l d6-d7,-(a7) *Preserve registers2984 clr.w d7 *Clear sum2985 bra chksum02 *Jump into loop2986 * 2987 chksum01: move.l 8(a6),a0 *Get buffer address2988 move.w (a0),d0 *Get word2989 add.w d0,d7 *Add to checksum in d72990 addq.l #2,8(a6) *Update buffer address2991 * 2992 chksum02: move.w 12(a6),d0 *Get word count2993 subq.w #1,12(a6) *Decrement it2994 tst.w d0 *Done ?2995 bne chksum01 *Loop if not2996 * 2997 move.w d7,d0 *Put result in d02983 movem.l d6-d7,-(a7) | Preserve registers 2984 clr.w d7 | Clear sum 2985 bra chksum02 | Jump into loop 2986 2987 chksum01: 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 2992 chksum02: move.w 12(a6),d0 | Get word count 2993 subq.w #1,12(a6) | Decrement it 2994 tst.w d0 | Done ? 2995 bne chksum01 | Loop if not 2996 2997 move.w d7,d0 | Put result in d0 2998 2998 tst.l (a7)+ 2999 movem.l (a7)+,d7 *Restore registers2999 movem.l (a7)+,d7 | Restore registers 3000 3000 unlk a6 3001 rts *Return to caller3002 * 3003 .page 3004 * 3005 *mult32 -- 32 bit signed multiply3006 *------ ----------------------3001 rts | Return to caller 3002 3003 .page 3004 3005 | mult32 -- 32 bit signed multiply 3006 | ------ ---------------------- 3007 3007 mult32: link a6,#-4 3008 3008 clr.w d2 3009 3009 tst.l 8(a6) 3010 3010 bge mult32a 3011 * 3011 3012 3012 neg.l 8(a6) 3013 3013 addq.w #1,d2 3014 * 3014 3015 3015 mult32a: tst.l 12(a6) 3016 3016 bge mult32b 3017 * 3017 3018 3018 neg.l 12(a6) 3019 3019 addq.w #1,d2 3020 * 3020 3021 3021 mult32b: move.w 10(a6),d0 3022 3022 mulu 14(a6),d0 … … 3032 3032 btst #0,d2 3033 3033 beq mult32c 3034 * 3034 3035 3035 neg.l d0 3036 * 3036 3037 3037 mult32c: unlk a6 3038 3038 rts 3039 * 3040 .page 3041 * 3042 *rand -- Generate a random number3043 *---- ------------------------3044 rand: link a6,#-4 *Reserve stack for temps3045 tst.l rseed *See if the seed is zero3046 bne rand01 *Jump if not3047 * 3048 move.l _hz_200,d0 *Pick up the 200 Hz clock3049 moveq.l #16,d1 *Shift it left3050 asl.l d1,d0 *...3051 or.l _hz_200,d0 *OR in current 200 Hz clock3052 move.l d0,rseed *Use that as the seed3053 * 3054 rand01: move.l # $BB40E62D,-(a7) *Put PI on the stack3055 move.l rseed,-(a7) *... and rseed, too3056 bsr mult32 *Multiply them3057 addq.l #8,a7 *Cleanup stack3058 addq.l #1,d0 *Add 1 to the result3059 move.l d0,rseed *Save as new seed3039 3040 .page 3041 3042 | rand -- Generate a random number 3043 | ---- ------------------------ 3044 rand: link a6,#-4 | Reserve stack for temps 3045 tst.l rseed | See if the seed is zero 3046 bne rand01 | Jump if not 3047 3048 move.l _hz_200,d0 | Pick up the 200 Hz clock 3049 moveq.l #16,d1 | Shift it left 3050 asl.l d1,d0 | ... 3051 or.l _hz_200,d0 | OR in current 200 Hz clock 3052 move.l d0,rseed | Use that as the seed 3053 3054 rand01: move.l #0xBB40E62D,-(a7) | Put PI on the stack 3055 move.l rseed,-(a7) | ... and rseed, too 3056 bsr mult32 | Multiply them 3057 addq.l #8,a7 | Cleanup stack 3058 addq.l #1,d0 | Add 1 to the result 3059 move.l d0,rseed | Save as new seed 3060 3060 move.l rseed,d0 3061 asr.l #8,d0 *Make it a 24 bit number3062 and.l # $FFFFFF,d0 *...3063 unlk a6 *Release stack3064 rts *Return to caller3065 * 3066 .page 3067 * 3068 *protobt -- Generate a prototype boot sector3069 *------- --------------------------------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 | ------- -------------------------------- 3070 3070 protobt: link a6,#-6 3071 movem.l d5-d7/a5,-(a7) *Save registers3072 tst.w 18(a6) *Test execflg3073 bge protbt03 *Jump if set3074 * 3075 move.w #256,(a7) *Count = 256 words3076 move.l 8(a6),-(a7) *Address of buffer3077 bsr chksum *Calculate checksum3078 addq.l #4,a7 *Cleanup stack3079 cmp.w # $1234,d0 *Boot checksum ?3080 beq protbt01 *Jump if so3081 * 3082 clr.w d0 *Not executable3071 movem.l d5-d7/a5,-(a7) | Save registers 3072 tst.w 18(a6) | Test execflg 3073 bge protbt03 | Jump if set 3074 3075 move.w #256,(a7) | Count = 256 words 3076 move.l 8(a6),-(a7) | Address of buffer 3077 bsr chksum | Calculate checksum 3078 addq.l #4,a7 | Cleanup stack 3079 cmp.w #0x1234,d0 | Boot checksum ? 3080 beq protbt01 | Jump if so 3081 3082 clr.w d0 | Not executable 3083 3083 bra protbt02 3084 * 3085 protbt01: moveq.l #1,d0 *Executable3086 * 3087 protbt02: move.w d0,18(a6) *Set execflg3088 * 3089 protbt03: tst.l 12(a6) *Serial number ?3090 blt protbt07 *Jump if not to be changed3091 * 3092 move.l 12(a6),d0 *Get it into d03093 cmp.l # $FFFFFF,d0 * > $FFFFFF3094 ble protbt04 *Jump if not3095 * 3096 bsr rand *Generate a random number3097 move.l d0,12(a6) *Save as s/n3098 * 3099 protbt04: clr.w d7 *Clear counter3100 bra protbt06 *Enter move loop3101 * 3102 .page 3103 * 3104 protbt05: move.l 12(a6),d0 *Get s/n3105 and.l # $FF,d0 *Isolate low 8 bits3106 move.w d7,a1 *Point to next byte3107 add.l 8(a6),a1 *...3108 move.b d0,8(a1) *Write byte in buffer3109 move.l 12(a6),d0 *Get s/n3110 asr.l #8,d0 *Shift right 8 bits3111 move.l d0,12(a6) *Save shifted value3112 addq.w #1,d7 *Update counter3113 * 3114 protbt06: cmp.w #3,d7 *See if we're done3115 blt protbt05 *Loop if not3116 * 3117 protbt07: tst.w 16(a6) *Diskette size ?3118 blt protbt10 *Jump if not to be changed3119 * 3120 move.w 16(a6),d6 *Get diskette size3121 muls.w #19,d6 *... times 19 as pointer3122 clr.w d7 *Clear counter3123 bra protbt09 *Go move in BPB3124 * 3125 protbt08: move.w d7,a0 *Get counter3126 add.l 8(a6),a0 *Add base of buffer3127 move.w d6,a1 *Get BPB pointer3128 add.l #pbpbtab,a1 *Add base of prototype BPB's3129 move.b (a1),11(a0) *Copy BPB data3130 addq.w #1,d6 *Update pointer3131 addq.w #1,d7 *Update counter3132 * 3133 protbt09: cmp.w #19,d7 *Done ?3134 blt protbt08 *Loop if not3135 * 3084 3085 protbt01: moveq.l #1,d0 | Executable 3086 3087 protbt02: move.w d0,18(a6) | Set execflg 3088 3089 protbt03: 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 3099 protbt04: clr.w d7 | Clear counter 3100 bra protbt06 | Enter move loop 3101 3102 .page 3103 3104 protbt05: 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 3114 protbt06: cmp.w #3,d7 | See if we're done 3115 blt protbt05 | Loop if not 3116 3117 protbt07: 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 3125 protbt08: 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 3133 protbt09: cmp.w #19,d7 | Done ? 3134 blt protbt08 | Loop if not 3135 3136 3136 protbt10: clr.w -6(a6) 3137 3137 move.l 8(a6),-4(a6) 3138 3138 bra protbt12 3139 * 3140 .page 3141 * 3142 protbt11: move.l -4(a6),a0 *Get buffer pointer3143 move.w (a0),d0 *Get word from buffer3144 add.w d0,-6(a6) *Sum for checksum3145 addq.l #2,-4(a6) *Point at next word3146 * 3147 protbt12: move.l 8(a6),d0 *Get buffer address3148 add.l # $1FE,d0 *Plus sector length3149 cmp.l -4(a6),d0 *Done ?3150 bhi protbt11 *Loop if not3151 * 3152 move.w # $1234,d0 *Checksum for boot sector3153 sub.w -6(a6),d0 *Subtract checksum for buffer3139 3140 .page 3141 3142 protbt11: 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 3147 protbt12: move.l 8(a6),d0 | Get buffer address 3148 add.l #0x1FE,d0 | Plus sector length 3149 cmp.l -4(a6),d0 | Done ? 3150 bhi protbt11 | Loop if not 3151 3152 move.w #0x1234,d0 | Checksum for boot sector 3153 sub.w -6(a6),d0 | Subtract checksum for buffer 3154 3154 move.l -4(a6),a1 3155 move.w d0,(a1) *Store checksum in buffer3156 tst.w 18(a6) *Check execflg3157 bne protbt13 *Boot sector to be executable ?3158 * 3159 move.l -4(a6),a0 *Mung checksum so it's not3155 move.w d0,(a1) | Store checksum in buffer 3156 tst.w 18(a6) | Check execflg 3157 bne protbt13 | Boot sector to be executable ? 3158 3159 move.l -4(a6),a0 | Mung checksum so it's not 3160 3160 addq.w #1,(a0) 3161 * 3161 3162 3162 protbt13: tst.l (a7)+ 3163 movem.l (a7)+,d6-d7/a5 *Restore registers3164 unlk a6 *Release stack3165 rts *Return to caller3166 * 3167 .endc 3168 * 3169 *criter -- Critical error handler3170 *------ ----------------------3171 criter: move.l critvec,-(a7) *Put error vector on stack3172 moveq.l #-1,d0 *Set default error return3173 rts *"Return" to handler3174 * 3175 .page 3176 * 3163 movem.l (a7)+,d6-d7/a5 | Restore registers 3164 unlk a6 | Release stack 3165 rts | Return to caller 3166 3167 .endc 3168 3169 | criter -- Critical error handler 3170 | ------ ---------------------- 3171 criter: move.l critvec,-(a7) | Put error vector on stack 3172 moveq.l #-1,d0 | Set default error return 3173 rts | "Return" to handler 3174 3175 .page 3176 3177 3177 .ifne BUCHLA 3178 * 3179 *api_int -- Analog processor interrupt handler3180 *------- ----------------------------------3181 api_int: movem.l d0-d1/a0-a1,-(a7) *Save registers3182 clr.l d0 *Read input port3183 move.b ANALOG,d0 *... into d0[7..0]3184 move.b d0,api_inp *... and api_inp3185 btst #7,d0 *Check for signal number flag3186 bne api_s0a *Jump if signal number read3187 * 3188 lea api_tv,a0 *Get api_tv base in a03189 clr.w d1 *Get api_sv in d13190 move.b api_sv,d1 *...3191 cmpi.b #6,d1 *Check range3192 bgt api_sve *Jump if out of range3193 * 3194 lsl.w #2,d1 *Develop jump address3195 move.l 0(a0,d1.W),a1 *... from api_tv in a13196 jmp (a1) *Jump to state handler3197 * 3198 api_s0: btst #7,d0 *Check for signal number flag3199 beq api_ret *Jump if not signal number3200 * 3201 api_s0a: clr.b api_val *Clear value byte3202 andi.b # $7F,d0 *Mask off signal number flag3203 cmpi.b #82,d0 *See if it's in range3204 bgt api_err *Jump if out of range (GT 82)3205 * 3206 move.b d0,api_sig *Store signal number3207 beq api_pub *Jump if it was "all off"3208 * 3209 lea api_tab,a0 *Get sv table base3210 move.b 0(a0,d0.W),api_sv *Set sv for next time3211 * 3212 api_ret: movem.l (a7)+,d0-d1/a0-a1 *Restore registers3213 rte *Return to interrupted code3214 * 3215 api_err: move.b d0,api_bug *Catch the bug3216 clr.b api_sv *Force state zero3217 bra api_ret *Go back to interrupted code3218 * 3219 api_sve: move.b d1,api_svb *Catch the bug3220 clr.b api_sv *Force state zero3221 bra api_ret *Go back to interrupted code3222 * 3223 .page 3224 api_s1: btst #0,d0 *See if it takes a value3225 beq api_s1a *Jump if not3226 * 3227 move.b #2,api_sv *Set sv for state 23228 bra api_ret *Go return from interrupt3229 * 3230 api_s1a: clr.b api_val *Clear value byte3231 bra api_pub *Go output to fifo3232 * 3233 api_s2: ori.b # $80,d0 *Set status = 13234 move.b d0,api_val *Set value byte3235 bra api_pub *Go output to fifo3236 * 3237 api_s3: ror.b #1,d0 *Set status in value byte3238 andi.b # $80,d0 *...3239 move.b d0,api_val *...3240 move.b #4,api_sv *Set sv for state 43241 bra api_ret *Go return from interrupt3242 * 3243 api_s4: or.b d0,api_val *Set value byte3244 bra api_pub *Go output to fifo3245 * 3246 api_s5: ror.b #1,d0 *Set status in value byte3247 andi.b # $80,d0 *...3248 * 3249 api_s6: move.b d0,api_val *Set value byte3250 * 3251 api_pub: movea.l api_fi,a0 *Get fifo input pointer in a03252 move.w api_sig,(a0)+ *Store new input3253 cmpa.l #api_fe,a0 *Wrap around ?3254 blt api_pb1 *Jump if not3255 * 3256 movea.l #api_fum,a0 *Wrap input pointer to start3257 * 3258 api_pb1: move.l a0,api_fi *Update input pointer3259 cmpa.l api_fo,a0 *Buffer full ?3260 bne api_pb3 *Jump if not3261 * 3262 movea.l api_fo,a1 *Get fifo output pointer in a13263 adda.l #2,a1 *Increment it3264 cmpa.l #api_fe,a1 *Wrap around ?3265 blt api_pb2 *Jump if not3266 * 3267 movea.l #api_fum,a1 *Wrap output pointer to start3268 * 3269 api_pb2: move.l a1,api_fo *Set new output pointer3270 * 3271 api_pb3: clr.b api_sv *Set state to 03272 bra api_ret *Return from interrupt3273 * 3274 .page 3275 * 3276 *api_get -- Get analog input3277 *------- ----------------3278 api_get: move.w sr,-(a7) *Save status register3279 ori.w #IPL3,sr *Disable ANALOG I/O interrupts3280 movea.l api_fo,a0 *Get fifo output pointer3281 cmpa.l api_fi,a0 *See if fifo is empty3282 bne api_g1 *Jump if not3283 * 3284 moveq.l #-1,d0 *Set empty-fifo value3285 move.w (a7)+,sr *Restore interrupt mask3286 rts *Return to caller3287 * 3288 api_g1: clr.l d0 *Get fifo value3289 move.w (a0)+,d0 *...3290 cmpa.l #api_fe,a0 *See if pointer wrapped3291 blt api_g2 *Jump if not3292 * 3293 movea.l #api_fum,a0 *Wrap the pointer around3294 * 3295 api_g2: move.l a0,api_fo *Update pointer3296 move.w (a7)+,sr *Restore interrupt mask3297 rts *Return to caller3298 * 3299 *api_zap -- clear analog I/O FIFO3300 *------- ---------------------3301 api_zap: move.w sr,-(a7) *Save status register3302 ori.w #IPL3,sr *Disable ANALOG I/O interrupts3303 move.l #api_fum,api_fi *Clear analog processor fifo3304 move.l #api_fum,api_fo *...3305 move.w (a7)+,sr *Restore interrupt mask3178 3179 | api_int -- Analog processor interrupt handler 3180 | ------- ---------------------------------- 3181 api_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 3198 api_s0: btst #7,d0 | Check for signal number flag 3199 beq api_ret | Jump if not signal number 3200 3201 api_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 3212 api_ret: movem.l (a7)+,d0-d1/a0-a1 | Restore registers 3213 rte | Return to interrupted code 3214 3215 api_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 3219 api_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 3224 api_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 3230 api_s1a: clr.b api_val | Clear value byte 3231 bra api_pub | Go output to fifo 3232 3233 api_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 3237 api_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 3243 api_s4: or.b d0,api_val | Set value byte 3244 bra api_pub | Go output to fifo 3245 3246 api_s5: ror.b #1,d0 | Set status in value byte 3247 andi.b #0x80,d0 | ... 3248 3249 api_s6: move.b d0,api_val | Set value byte 3250 3251 api_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 3258 api_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 3269 api_pb2: move.l a1,api_fo | Set new output pointer 3270 3271 api_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 | ------- ---------------- 3278 api_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 3288 api_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 3295 api_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 | ------- --------------------- 3301 api_zap: move.w sr,-(a7) | Save status register 3302 ori.w #IPL3,sr | Disable ANALOG I/O interrupts 3303 move.l #api_fum,api_fi | Clear analog processor fifo 3304 move.l #api_fum,api_fo | ... 3305 move.w (a7)+,sr | Restore interrupt mask 3306 3306 rts 3307 * 3308 .endc 3309 * 3310 .page 3311 ************************************************************************* 3312 * * 3313 * Constant definitions * 3314 * -------------------- * 3315 ************************************************************************* 3316 * 3307 3308 .endc 3309 3310 .page 3311 ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 3312 | | 3313 | Constant definitions | 3314 | -------------------- | 3315 ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 3316 3317 3317 .even 3318 * 3318 3319 3319 .ifne BUCHLA 3320 * 3321 *Buchla 700 tables:3322 * 3323 *t13tab -- Trap-13 pointer table -- Primary BIOS functions3324 *------ -----------------------------------------------3325 t13tab: dc.w 12 *Number of Trap-13 routines3326 * 3327 dc.l nullrts *0 - (getmpb)3328 dc.l bconstat *1 - bconstat3329 dc.l bconin *2 - bconin3330 dc.l bconout *3 - bconout3331 dc.l rwabs *4 - rwabs3332 dc.l setexec *5 - setexec3333 dc.l nullrts *6 - (tickcal)3334 dc.l getbpb *7 - getbpb3335 dc.l bcostat *8 - bcostat3336 dc.l mediach *9 - mediach3337 dc.l drvmap *10 - drvmap3338 dc.l nullrts *11 - (shift)3339 * 3340 .page 3341 * 3342 *t14tab -- Trap-14 pointer table -- Extended BIOS functions (Buchla 700 only)3343 *------ ------------------------------------------------------------------3344 t14tab: dc.w 10 *Number of trap14 routines3345 * 3346 dc.l piorec *0 - Get iorec address3347 dc.l setport *1 - Set ACIA parameters3348 dc.l floprd *2 - Read floppy3349 dc.l flopwr *3 - Write floppy3350 dc.l flopfmt *4 - Format floppy3351 dc.l flopver *5 - Verify floppy3352 dc.l protobt *6 - Create prototype boot sec.3353 dc.l rand *7 - Generate random number3354 dc.l api_get *8 - Get analog input3355 dc.l api_zap *9 - Clear analog FIFO3356 * 3357 .endc 3358 * 3320 3321 | Buchla 700 tables: 3322 3323 | t13tab -- Trap-13 pointer table -- Primary BIOS functions 3324 | ------ ----------------------------------------------- 3325 t13tab: dc.w 12 | Number of Trap-13 routines 3326 3327 dc.l nullrts | 0 - (getmpb) 3328 dc.l bconstat | 1 - bconstat 3329 dc.l bconin | 2 - bconin 3330 dc.l bconout | 3 - bconout 3331 dc.l rwabs | 4 - rwabs 3332 dc.l setexec | 5 - setexec 3333 dc.l nullrts | 6 - (tickcal) 3334 dc.l getbpb | 7 - getbpb 3335 dc.l bcostat | 8 - bcostat 3336 dc.l mediach | 9 - mediach 3337 dc.l drvmap | 10 - drvmap 3338 dc.l nullrts | 11 - (shift) 3339 3340 .page 3341 3342 | t14tab -- Trap-14 pointer table -- Extended BIOS functions (Buchla 700 only) 3343 | ------ ------------------------------------------------------------------ 3344 t14tab: dc.w 10 | Number of trap14 routines 3345 3346 dc.l piorec | 0 - Get iorec address 3347 dc.l setport | 1 - Set ACIA parameters 3348 dc.l floprd | 2 - Read floppy 3349 dc.l flopwr | 3 - Write floppy 3350 dc.l flopfmt | 4 - Format floppy 3351 dc.l flopver | 5 - Verify floppy 3352 dc.l protobt | 6 - Create prototype boot sec. 3353 dc.l rand | 7 - Generate random number 3354 dc.l api_get | 8 - Get analog input 3355 dc.l api_zap | 9 - Clear analog FIFO 3356 3357 .endc 3358 3359 3359 .even 3360 * 3360 3361 3361 .ifeq BUCHLA 3362 * 3363 *NASA 3D Helmet tables:3364 * 3365 *t13tab -- Trap-13 pointer table -- Primary BIOS functions3366 *------ -----------------------------------------------3367 t13tab: dc.w 12 *Number of Trap-13 routines3368 * 3369 dc.l nullrts *0 - (getmpb)3370 dc.l bconstat *1 - bconstat3371 dc.l bconin *2 - bconin3372 dc.l bconout *3 - bconout3373 dc.l nullrts *4 - (rwabs)3374 dc.l setexec *5 - setexec3375 dc.l nullrts *6 - (tickcal)3376 dc.l nullrts *7 - (getbpb)3377 dc.l bcostat *8 - bcostat3378 dc.l nullrts *9 - (mediach)3379 dc.l nullrts *10 - (drvmap)3380 dc.l nullrts *11 - (shift)3381 * 3382 .page 3383 * 3384 *t14tab -- Trap-14 pointer table -- Extended BIOS functions (Buchla 700 only)3385 *------ ------------------------------------------------------------------3386 t14tab: dc.w 10 *Number of trap14 routines3387 * 3388 dc.l piorec *0 - Get iorec address3389 dc.l setport *1 - Set ACIA parameters3390 dc.l nullrts *2 - (Read floppy)3391 dc.l nullrts *3 - (Write floppy)3392 dc.l nullrts *4 - (Format floppy)3393 dc.l nullrts *5 - (Verify floppy)3394 dc.l nullrts *6 - (Create prototype boot sec.)3395 dc.l nullrts *7 - (Generate random number)3396 dc.l nullrts *8 - (Get analog input)3397 dc.l nullrts *9 - (Clear analog FIFO)3398 * 3399 .endc 3400 * 3401 .page 3402 * 3403 *cdt01 -- Character device dispatch table #1 -- input status3404 *----- --------------------------------------------------3405 cdt01: dc.l sr1ist *0 - PRT -- Printer3406 dc.l sr2ist *1 - AUX -- Serial-23407 dc.l sr2ist *2 - CON -- Console3408 * 3362 3363 | NASA 3D Helmet tables: 3364 3365 | t13tab -- Trap-13 pointer table -- Primary BIOS functions 3366 | ------ ----------------------------------------------- 3367 t13tab: dc.w 12 | Number of Trap-13 routines 3368 3369 dc.l nullrts | 0 - (getmpb) 3370 dc.l bconstat | 1 - bconstat 3371 dc.l bconin | 2 - bconin 3372 dc.l bconout | 3 - bconout 3373 dc.l nullrts | 4 - (rwabs) 3374 dc.l setexec | 5 - setexec 3375 dc.l nullrts | 6 - (tickcal) 3376 dc.l nullrts | 7 - (getbpb) 3377 dc.l bcostat | 8 - bcostat 3378 dc.l nullrts | 9 - (mediach) 3379 dc.l nullrts | 10 - (drvmap) 3380 dc.l nullrts | 11 - (shift) 3381 3382 .page 3383 3384 | t14tab -- Trap-14 pointer table -- Extended BIOS functions (Buchla 700 only) 3385 | ------ ------------------------------------------------------------------ 3386 t14tab: dc.w 10 | Number of trap14 routines 3387 3388 dc.l piorec | 0 - Get iorec address 3389 dc.l setport | 1 - Set ACIA parameters 3390 dc.l nullrts | 2 - (Read floppy) 3391 dc.l nullrts | 3 - (Write floppy) 3392 dc.l nullrts | 4 - (Format floppy) 3393 dc.l nullrts | 5 - (Verify floppy) 3394 dc.l nullrts | 6 - (Create prototype boot sec.) 3395 dc.l nullrts | 7 - (Generate random number) 3396 dc.l nullrts | 8 - (Get analog input) 3397 dc.l nullrts | 9 - (Clear analog FIFO) 3398 3399 .endc 3400 3401 .page 3402 3403 | cdt01 -- Character device dispatch table #1 -- input status 3404 | ----- -------------------------------------------------- 3405 cdt01: dc.l sr1ist | 0 - PRT -- Printer 3406 dc.l sr2ist | 1 - AUX -- Serial-2 3407 dc.l sr2ist | 2 - CON -- Console 3408 3409 3409 .ifne BUCHLA 3410 * 3411 dc.l mc1ist *3 - MC1 -- MIDI-13412 dc.l mc2ist *4 - MC2 -- MIDI-23413 * 3414 .endc 3415 * 3416 *cdt02 -- Character device dispatch table #2 -- input3417 *----- -------------------------------------------3418 cdt02: dc.l sr1inp *0 - PRT -- Printer3419 dc.l sr2inp *1 - AUX -- Serial-23420 dc.l sr2inp *2 - CON -- Console3421 * 3410 3411 dc.l mc1ist | 3 - MC1 -- MIDI-1 3412 dc.l mc2ist | 4 - MC2 -- MIDI-2 3413 3414 .endc 3415 3416 | cdt02 -- Character device dispatch table #2 -- input 3417 | ----- ------------------------------------------- 3418 cdt02: dc.l sr1inp | 0 - PRT -- Printer 3419 dc.l sr2inp | 1 - AUX -- Serial-2 3420 dc.l sr2inp | 2 - CON -- Console 3421 3422 3422 .ifne BUCHLA 3423 * 3424 dc.l mc1inp *3 - MC1 -- MIDI-13425 dc.l mc2inp *4 - MC2 -- MIDI-23426 * 3427 .endc 3428 * 3429 *cdt03 -- Character device dispatch table #3 -- output3430 *----- --------------------------------------------3431 cdt03: dc.l sr1out *0 - PRT -- Printer3432 dc.l sr2out *1 - AUX -- Serial-23433 dc.l sr2out *2 - CON -- Console3423 3424 dc.l mc1inp | 3 - MC1 -- MIDI-1 3425 dc.l mc2inp | 4 - MC2 -- MIDI-2 3426 3427 .endc 3428 3429 | cdt03 -- Character device dispatch table #3 -- output 3430 | ----- -------------------------------------------- 3431 cdt03: dc.l sr1out | 0 - PRT -- Printer 3432 dc.l sr2out | 1 - AUX -- Serial-2 3433 dc.l sr2out | 2 - CON -- Console 3434 3434 .ifne BUCHLA 3435 * 3436 dc.l mc1out *3 - MC1 -- MIDI-13437 dc.l mc2out *4 - MC2 -- MIDI-23438 * 3439 .endc 3440 * 3441 *cdt04 -- Character device dispatch table #4 -- output status3442 *----- ---------------------------------------------------3443 cdt04: dc.l sr1ost *0 - PRT -- Printer3444 dc.l sr2ost *1 - AUX -- Serial-23445 dc.l sr2ost *2 - CON -- Console3435 3436 dc.l mc1out | 3 - MC1 -- MIDI-1 3437 dc.l mc2out | 4 - MC2 -- MIDI-2 3438 3439 .endc 3440 3441 | cdt04 -- Character device dispatch table #4 -- output status 3442 | ----- --------------------------------------------------- 3443 cdt04: dc.l sr1ost | 0 - PRT -- Printer 3444 dc.l sr2ost | 1 - AUX -- Serial-2 3445 dc.l sr2ost | 2 - CON -- Console 3446 3446 .ifne BUCHLA 3447 * 3448 dc.l mc1ost *3 - MC1 -- MIDI-13449 dc.l mc2ost *4 - MC2 -- MIDI-23450 * 3451 .endc 3452 * 3453 .page 3454 * 3455 *iorec defaults:3456 *---------------3457 *Serial-1:3458 *---------3447 3448 dc.l mc1ost | 3 - MC1 -- MIDI-1 3449 dc.l mc2ost | 4 - MC2 -- MIDI-2 3450 3451 .endc 3452 3453 .page 3454 3455 | iorec defaults: 3456 | --------------- 3457 | Serial-1: 3458 | --------- 3459 3459 sr1dflt: dc.l sr1ibuf 3460 3460 dc.w SR1IBS … … 3472 3472 dc.b 0,0 3473 3473 dc.w 0,0 3474 * 3475 *Serial-2:3476 *---------3474 3475 | Serial-2: 3476 | --------- 3477 3477 sr2dflt: dc.l sr2ibuf 3478 3478 dc.w SR2IBS … … 3490 3490 dc.b 0,0 3491 3491 dc.w 0,0 3492 * 3493 .page 3494 * 3492 3493 .page 3494 3495 3495 .ifne BUCHLA 3496 * 3497 *MIDI-1:3498 *-------3496 3497 | MIDI-1: 3498 | ------- 3499 3499 mc1dflt: dc.l mc1ibuf 3500 3500 dc.w MC1IBS … … 3512 3512 dc.b 0,0 3513 3513 dc.w 0,0 3514 * 3515 *MIDI-2:3516 *-------3514 3515 | MIDI-2: 3516 | ------- 3517 3517 mc2dflt: dc.l mc2ibuf 3518 3518 dc.w MC2IBS … … 3530 3530 dc.b 0,0 3531 3531 dc.w 0,0 3532 * 3533 .endc 3534 * 3535 .page 3536 * 3537 *brtable -- Baud rate setup table3538 *------- ---------------------3539 brtable: dc.b BR_19K2 *0 - 19200 baud3540 dc.b BR_9600 *1 - 9600 baud3541 dc.b BR_4800 *2 - 4800 baud3542 dc.b BR_3600 *3 - 3600 baud3543 dc.b BR_2400 *4 - 2400 baud3544 dc.b BR_7200 *5 - 7200 baud (2000 on Atari)3545 dc.b BR_1800 *6 - 1800 baud3546 dc.b BR_1200 *7 - 1200 baud3547 dc.b BR_600 *8 - 600 baud3548 dc.b BR_300 *9 - 300 baud3549 * 3550 *iortab -- iorec pointer table3551 *------ -------------------3552 iortab: dc.l sr1iorec *0 - PRT Serial-1 Printer3553 dc.l sr2iorec *1 - AUX Serial-2 Host3554 dc.l sr2iorec *2 - CON Serial-2 Console3555 * 3532 3533 .endc 3534 3535 .page 3536 3537 | brtable -- Baud rate setup table 3538 | ------- --------------------- 3539 brtable: dc.b BR_19K2 | 0 - 19200 baud 3540 dc.b BR_9600 | 1 - 9600 baud 3541 dc.b BR_4800 | 2 - 4800 baud 3542 dc.b BR_3600 | 3 - 3600 baud 3543 dc.b BR_2400 | 4 - 2400 baud 3544 dc.b BR_7200 | 5 - 7200 baud (2000 on Atari) 3545 dc.b BR_1800 | 6 - 1800 baud 3546 dc.b BR_1200 | 7 - 1200 baud 3547 dc.b BR_600 | 8 - 600 baud 3548 dc.b BR_300 | 9 - 300 baud 3549 3550 | iortab -- iorec pointer table 3551 | ------ ------------------- 3552 iortab: dc.l sr1iorec | 0 - PRT Serial-1 Printer 3553 dc.l sr2iorec | 1 - AUX Serial-2 Host 3554 dc.l sr2iorec | 2 - CON Serial-2 Console 3555 3556 3556 .ifne BUCHLA 3557 * 3558 dc.l mc1iorec *3 - MC1 MIDI-1 MIDI port #13559 dc.l mc2iorec *4 - MC2 MIDI-2 MIDI port #23560 * 3561 .endc 3562 * 3563 *aciatab -- iorec and ACIA pointer table3564 *------- ----------------------------3565 aciatab: dc.l sr1iorec,SR1ACIA *0 - PRT Serial-13566 dc.l sr2iorec,SR2ACIA *1 - AUX Serial-23567 dc.l sr2iorec,SR2ACIA *2 - CON Serial-23568 * 3557 3558 dc.l mc1iorec | 3 - MC1 MIDI-1 MIDI port #1 3559 dc.l mc2iorec | 4 - MC2 MIDI-2 MIDI port #2 3560 3561 .endc 3562 3563 | aciatab -- iorec and ACIA pointer table 3564 | ------- ---------------------------- 3565 aciatab: dc.l sr1iorec,SR1ACIA | 0 - PRT Serial-1 3566 dc.l sr2iorec,SR2ACIA | 1 - AUX Serial-2 3567 dc.l sr2iorec,SR2ACIA | 2 - CON Serial-2 3568 3569 3569 .ifne BUCHLA 3570 * 3571 dc.l mc1iorec,MC1ACIA *3 - MC1 MIDI-13572 dc.l mc2iorec,MC2ACIA *4 - MC2 MIDI-23573 * 3574 .endc 3575 * 3576 .page 3577 * 3570 3571 dc.l mc1iorec,MC1ACIA | 3 - MC1 MIDI-1 3572 dc.l mc2iorec,MC2ACIA | 4 - MC2 MIDI-2 3573 3574 .endc 3575 3576 .page 3577 3578 3578 .ifne BUCHLA 3579 * 3580 *pbpbtab -- Prototype BPB data table (BPS..NHID) 19 bytes per entry3581 *------- ---------------------------------------------------------3582 * 3583 *0 -- 40 tracks, single sided (180K)3584 * 3585 pbpbtab: dc.b $00,$02,$01,$01,$00,$02,$40,$003586 dc.b $68,$01,$FC,$02,$00,$09,$00,$013587 dc.b $00,$00,$003588 * 3589 *1 -- 40 tracks, double sided (360K)3590 * 3591 dc.b $00,$02,$02,$01,$00,$02,$70,$003592 dc.b $D0,$02,$FD,$02,$00,$09,$00,$023593 dc.b $00,$00,$003594 * 3595 *2 -- 80 tracks, single sided (360K)3596 * 3597 dc.b $00,$02,$02,$01,$00,$02,$70,$003598 dc.b $D0,$02,$F8,$05,$00,$09,$00,$013599 dc.b $00,$00,$003600 * 3601 *3 -- 80 tracks, double sided (720K)3602 * 3603 dc.b $00,$02,$02,$01,$00,$02,$70,$003604 dc.b $A0,$05,$F9,$05,$00,$09,$00,$023605 dc.b $00,$00,$003606 * 3607 *VSDD initialization table3608 * 3579 3580 | pbpbtab -- Prototype BPB data table (BPS..NHID) 19 bytes per entry 3581 | ------- --------------------------------------------------------- 3582 3583 | 0 -- 40 tracks, single sided (180K) 3584 3585 pbpbtab: dc.b 0x00,0x02,0x01,0x01,0x00,0x02,0x40,0x00 3586 dc.b 0x68,0x01,0xFC,0x02,0x00,0x09,0x00,0x01 3587 dc.b 0x00,0x00,0x00 3588 3589 | 1 -- 40 tracks, double sided (360K) 3590 3591 dc.b 0x00,0x02,0x02,0x01,0x00,0x02,0x70,0x00 3592 dc.b 0xD0,0x02,0xFD,0x02,0x00,0x09,0x00,0x02 3593 dc.b 0x00,0x00,0x00 3594 3595 | 2 -- 80 tracks, single sided (360K) 3596 3597 dc.b 0x00,0x02,0x02,0x01,0x00,0x02,0x70,0x00 3598 dc.b 0xD0,0x02,0xF8,0x05,0x00,0x09,0x00,0x01 3599 dc.b 0x00,0x00,0x00 3600 3601 | 3 -- 80 tracks, double sided (720K) 3602 3603 dc.b 0x00,0x02,0x02,0x01,0x00,0x02,0x70,0x00 3604 dc.b 0xA0,0x05,0xF9,0x05,0x00,0x09,0x00,0x02 3605 dc.b 0x00,0x00,0x00 3606 3607 | VSDD initialization table 3608 3609 3609 .even 3610 * 3611 vsddtab: dc.w $8252 *R0 Mode word 03612 dc.w $E474 *R1 Mode word 13613 dc.w $0006 *R2 Register window base3614 dc.w $0100 *R3 Data window base3615 dc.w $0000 *R4 Data length mask3616 dc.w $0000 *R5 Data segment base3617 dc.w $0001 *R6 Priority access count3618 dc.w $0040 *R7 ODT base3619 dc.w $0080 *R8 AT base3620 dc.w $0010 *R9 CLT base3621 dc.w $0011 *R10 CG bases3622 dc.w $0000 *R11 AT counter (R/O)3623 * 3624 dc.w $0C08 *R12 HC0 = 3, VC0 = 83625 dc.w $140A *R13 HC1 = 5, VC1 = 103626 dc.w $9568 *R14 HC2 = 37, VC2 = 3603627 dc.w $A16A *R15 HC3 = 40, VC3 = 3623628 * 3629 vsddit01: dc.w $8253 *R0 with UCF = 1, DEN = 03630 vsddit02: dc.w $825B *R0 with UCF = 1, DEN = 13631 * 3632 .page 3633 * 3634 *analog processor input state table3635 * 3636 api_tab: dc.b 0,1,1,1,1,1,1,1,1,1 *0..93637 dc.b 1,1,1,1,1,1,1,1,1,1 *10..193638 dc.b 1,1,1,1,1 *20..243639 dc.b 3,3,3,3,3 *25..293640 dc.b 3,3,3,3,3,3,3,3,3 *30..383641 dc.b 5 *393642 dc.b 5,5,5,5,5,5,5,5,5,5 *40..493643 dc.b 5,5,5 *50..523644 dc.b 3,3,3,3,3,3,3 *53..593645 dc.b 5,5,5,5,5,5,5,5,5,5 *60..693646 dc.b 5,5,5 *70..723647 dc.b 6,6,6,6,6,6,6 *73..793648 dc.b 6,6,6 *80..823649 * 3610 3611 vsddtab: dc.w 0x8252 | R0 Mode word 0 3612 dc.w 0xE474 | R1 Mode word 1 3613 dc.w 0x0006 | R2 Register window base 3614 dc.w 0x0100 | R3 Data window base 3615 dc.w 0x0000 | R4 Data length mask 3616 dc.w 0x0000 | R5 Data segment base 3617 dc.w 0x0001 | R6 Priority access count 3618 dc.w 0x0040 | R7 ODT base 3619 dc.w 0x0080 | R8 AT base 3620 dc.w 0x0010 | R9 CLT base 3621 dc.w 0x0011 | R10 CG bases 3622 dc.w 0x0000 | R11 AT counter (R/O) 3623 3624 dc.w 0x0C08 | R12 HC0 = 3, VC0 = 8 3625 dc.w 0x140A | R13 HC1 = 5, VC1 = 10 3626 dc.w 0x9568 | R14 HC2 = 37, VC2 = 360 3627 dc.w 0xA16A | R15 HC3 = 40, VC3 = 362 3628 3629 vsddit01: dc.w 0x8253 | R0 with UCF = 1, DEN = 0 3630 vsddit02: dc.w 0x825B | R0 with UCF = 1, DEN = 1 3631 3632 .page 3633 3634 | analog processor input state table 3635 3636 api_tab: dc.b 0,1,1,1,1,1,1,1,1,1 | 0..9 3637 dc.b 1,1,1,1,1,1,1,1,1,1 | 10..19 3638 dc.b 1,1,1,1,1 | 20..24 3639 dc.b 3,3,3,3,3 | 25..29 3640 dc.b 3,3,3,3,3,3,3,3,3 | 30..38 3641 dc.b 5 | 39 3642 dc.b 5,5,5,5,5,5,5,5,5,5 | 40..49 3643 dc.b 5,5,5 | 50..52 3644 dc.b 3,3,3,3,3,3,3 | 53..59 3645 dc.b 5,5,5,5,5,5,5,5,5,5 | 60..69 3646 dc.b 5,5,5 | 70..72 3647 dc.b 6,6,6,6,6,6,6 | 73..79 3648 dc.b 6,6,6 | 80..82 3649 3650 3650 .even 3651 * 3652 *analog processor state transfer vector3653 * 3651 3652 | analog processor state transfer vector 3653 3654 3654 api_tv: dc.l api_s0,api_s1,api_s2,api_s3 3655 3655 dc.l api_s4,api_s5,api_s6 3656 * 3657 .endc 3658 * 3659 .page 3660 ************************************************************************* 3661 * * 3662 * RAM storage definitions * 3663 * ----------------------- * 3664 ************************************************************************* 3665 * 3656 3657 .endc 3658 3659 .page 3660 ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 3661 | | 3662 | RAM storage definitions | 3663 | ----------------------- | 3664 ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| 3665 3666 3666 .bss 3667 3667 .even 3668 * 3669 *RAM data area3670 *-------------3671 *WARNING:3672 *--------3673 *The variables from timevec through rsarea are permanently assigned so3674 *that we can link to certain bios variables without having to link to the3675 *bios object file itself. Some of these get defined in hwdefs.s and in3676 *hwdefs.s so beware of changing them.3677 * 3678 timevec: ds.l 1 *System timer trap vector3679 critvec: ds.l 1 *Critical error handler vector3680 termvec: ds.l 1 *Process terminate hook vector3681 resvec3: ds.l 1 *Reserved vector 33682 resvec4: ds.l 1 *Reserved vector 43683 resvec5: ds.l 1 *Reserved vector 53684 resvec6: ds.l 1 *Reserved vector 63685 resvec7: ds.l 1 *Reserved vector 73686 * 3687 fc_sw: ds.w 1 *Frame clock switch (<0=dn, 0=off, >0=up)3688 fc_val: ds.l 1 *Frame clock value (0..FCMAX)3689 * 3690 _wzcrsh: ds.w 1 *Crash area: flag for ROMP3691 _crshsr: ds.w 1 *Crash area: SR3692 _crshpc: ds.l 1 *Crash area: PC3693 _crshsp: ds.l 1 *Crash area: SP3694 _crshus: ds.l 1 *Crash area: USP3695 _crshvc: ds.l 1 *Crash area: vector # in MS byte3696 _crshrg: ds.l 16 *Crash area: registers3697 _crshst: ds.w 16 *Crash area: top 16 words of stack3698 * 3699 *The area from biosram to SSTACK-1 is cleared on reset.3700 *------------------------------------------------------3701 biosram .equ * *Start of BIOS RAM variables3702 * 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 3678 timevec: ds.l 1 | System timer trap vector 3679 critvec: ds.l 1 | Critical error handler vector 3680 termvec: ds.l 1 | Process terminate hook vector 3681 resvec3: ds.l 1 | Reserved vector 3 3682 resvec4: ds.l 1 | Reserved vector 4 3683 resvec5: ds.l 1 | Reserved vector 5 3684 resvec6: ds.l 1 | Reserved vector 6 3685 resvec7: ds.l 1 | Reserved vector 7 3686 3687 fc_sw: ds.w 1 | Frame clock switch (<0=dn, 0=off, >0=up) 3688 fc_val: ds.l 1 | Frame clock value (0..FCMAX) 3689 3690 _wzcrsh: ds.w 1 | Crash area: flag for ROMP 3691 _crshsr: ds.w 1 | Crash area: SR 3692 _crshpc: ds.l 1 | Crash area: PC 3693 _crshsp: ds.l 1 | Crash area: SP 3694 _crshus: ds.l 1 | Crash area: USP 3695 _crshvc: ds.l 1 | Crash area: vector # in MS byte 3696 _crshrg: ds.l 16 | Crash area: registers 3697 _crshst: ds.w 16 | Crash area: top 16 words of stack 3698 3699 | The area from biosram to SSTACK-1 is cleared on reset. 3700 | ------------------------------------------------------ 3701 biosram: | Start of BIOS RAM variables 3702 3703 3703 .ifne BUCHLA 3704 * 3705 _hz_1k: ds.l 1 *1000 Hz clock3706 _hz_200: ds.l 1 *200 Hz clock3707 frclock: ds.l 1 *50 Hz clock3708 t1count: ds.w 1 *Timer 1 count3709 t2count: ds.w 1 *Timer 2 count3710 t3count: ds.w 1 *Timer 3 count3711 * 3712 seekrate: ds.w 1 *Seek rate3713 cdev: ds.w 1 *Current drive3714 ctrack: ds.w 1 *Current track3715 csect: ds.w 1 *Current sector3716 cside: ds.w 1 *Current side3717 ccount: ds.w 1 *Current sector count3718 spt: ds.w 1 *Sectors per track3719 interlv: ds.w 1 *Sector interleave count3720 virgin: ds.w 1 *Initial formatting data3721 deferr: ds.w 1 *Default error number3722 curerr: ds.w 1 *Current error number3723 * 3724 cdma: ds.l 1 *Current DMA address3725 edma: ds.l 1 *Ending DMA address3726 tmpdma: ds.l 1 *Temporary DMA address3727 * 3728 .endc 3729 * 3730 rseed: ds.l 1 *Random number seed3731 * 3732 savptr: ds.l 1 *Pointer to register save area3733 * 3734 _rsflag: ds.l 1 *Register save area overflow flag3735 ds.l 18 *32 *Register save area (32 levels)3736 rsarea: ds.l 1 *Dummy long word at top of save area3737 * 3738 * ***** end of the permanently assigned bios variables ***** 3739 * 3740 .page 3741 * 3704 3705 _hz_1k: ds.l 1 | 1000 Hz clock 3706 _hz_200: ds.l 1 | 200 Hz clock 3707 frclock: ds.l 1 | 50 Hz clock 3708 t1count: ds.w 1 | Timer 1 count 3709 t2count: ds.w 1 | Timer 2 count 3710 t3count: ds.w 1 | Timer 3 count 3711 3712 seekrate: ds.w 1 | Seek rate 3713 cdev: ds.w 1 | Current drive 3714 ctrack: ds.w 1 | Current track 3715 csect: ds.w 1 | Current sector 3716 cside: ds.w 1 | Current side 3717 ccount: ds.w 1 | Current sector count 3718 spt: ds.w 1 | Sectors per track 3719 interlv: ds.w 1 | Sector interleave count 3720 virgin: ds.w 1 | Initial formatting data 3721 deferr: ds.w 1 | Default error number 3722 curerr: ds.w 1 | Current error number 3723 3724 cdma: ds.l 1 | Current DMA address 3725 edma: ds.l 1 | Ending DMA address 3726 tmpdma: ds.l 1 | Temporary DMA address 3727 3728 .endc 3729 3730 rseed: ds.l 1 | Random number seed 3731 3732 savptr: ds.l 1 | Pointer to register save area 3733 3734 _rsflag: ds.l 1 | Register save area overflow flag 3735 ds.l 18|32 | Register save area (32 levels) 3736 rsarea: ds.l 1 | Dummy long word at top of save area 3737 3738 | ||||| end of the permanently assigned bios variables ||||| 3739 3740 .page 3741 3742 3742 .ifne BUCHLA 3743 * 3744 acctim: ds.l 2 *Accumulated disk time table3745 maxactim: ds.l 1 *Maximum acctim value3746 hdv_init: ds.l 1 *Disk init vector3747 hdv_bpb: ds.l 1 *Disk get bpb vector3748 hdv_rw: ds.l 1 *Disk r/w vector3749 hdv_boot: ds.l 1 *Disk boot vector3750 hdv_mchg: ds.l 1 *Disk media change vector3751 drvbits: ds.l 1 *Drive map bits3752 dskbufp: ds.l 1 *Disk buffer pointer3753 .page 3754 nflops: ds.w 1 *Number of drives3755 disknum: ds.w 1 *Current disk number3756 booted: ds.w 1 *Most recent boot device or -13757 flock: ds.w 1 *Floppy semaphore3758 fverify: ds.w 1 *Floppy verify flag3759 * 3760 tdiv1: ds.w 1 *Timer divider 1 (divides _hz_1k)3761 tdiv2: ds.w 1 *Timer divider 2 (divides _hz_200)3762 * 3763 retrycnt: ds.w 1 *Re-try count3764 wpstatus: ds.w 1 *Write protect status table3765 wplatch: ds.w 1 *Write protect latch table3766 bootdev: ds.w 1 *Boot device number3767 * 3768 motoron: ds.w 1 *Motor-on flag3769 deslflag: ds.w 1 *Drive deselect flag3770 * 3771 .endc 3772 * 3773 flpsrsv: ds.w 1 *Status register save area3774 flpregs: ds.l 16 *Register save area3775 * 3743 3744 acctim: ds.l 2 | Accumulated disk time table 3745 maxactim: ds.l 1 | Maximum acctim value 3746 hdv_init: ds.l 1 | Disk init vector 3747 hdv_bpb: ds.l 1 | Disk get bpb vector 3748 hdv_rw: ds.l 1 | Disk r/w vector 3749 hdv_boot: ds.l 1 | Disk boot vector 3750 hdv_mchg: ds.l 1 | Disk media change vector 3751 drvbits: ds.l 1 | Drive map bits 3752 dskbufp: ds.l 1 | Disk buffer pointer 3753 .page 3754 nflops: ds.w 1 | Number of drives 3755 disknum: ds.w 1 | Current disk number 3756 booted: ds.w 1 | Most recent boot device or -1 3757 flock: ds.w 1 | Floppy semaphore 3758 fverify: ds.w 1 | Floppy verify flag 3759 3760 tdiv1: ds.w 1 | Timer divider 1 (divides _hz_1k) 3761 tdiv2: ds.w 1 | Timer divider 2 (divides _hz_200) 3762 3763 retrycnt: ds.w 1 | Re-try count 3764 wpstatus: ds.w 1 | Write protect status table 3765 wplatch: ds.w 1 | Write protect latch table 3766 bootdev: ds.w 1 | Boot device number 3767 3768 motoron: ds.w 1 | Motor-on flag 3769 deslflag: ds.w 1 | Drive deselect flag 3770 3771 .endc 3772 3773 flpsrsv: ds.w 1 | Status register save area 3774 flpregs: ds.l 16 | Register save area 3775 3776 3776 .ifne BUCHLA 3777 * 3778 dsb0: ds.l 1 *Drive A DSB3779 dsb1: ds.l 1 *Drive B DSB3780 * 3781 dskmode: ds.b 2 *Disk change mode table3782 dskerrs: ds.w 2 *Disk error code table3783 drvbpbs: ds.w 16 *2 *Disk BPB save area3784 * 3785 .endc 3786 * 3787 .page 3788 * 3789 sr1iorec: ds.b IORECLN *Serial-1 iorec structure3790 sr2iorec: ds.b IORECLN *Serial-2 iorec structure3791 * 3777 3778 dsb0: ds.l 1 | Drive A DSB 3779 dsb1: ds.l 1 | Drive B DSB 3780 3781 dskmode: ds.b 2 | Disk change mode table 3782 dskerrs: ds.w 2 | Disk error code table 3783 drvbpbs: ds.w 16|2 | Disk BPB save area 3784 3785 .endc 3786 3787 .page 3788 3789 sr1iorec: ds.b IORECLN | Serial-1 iorec structure 3790 sr2iorec: ds.b IORECLN | Serial-2 iorec structure 3791 3792 3792 .ifne BUCHLA 3793 * 3794 mc1iorec: ds.b IORECLN *MIDI-1 iorec structure3795 mc2iorec: ds.b IORECLN *MIDI-2 iorec structure3796 * 3797 .endc 3798 * 3799 sr1ibuf: ds.b SR1IBS *Serial-1 input buffer3800 sr1obuf: ds.b SR1OBS *Serial-1 output buffer3801 sr2ibuf: ds.b SR2IBS *Serial-2 input buffer3802 sr2obuf: ds.b SR2OBS *Serial-2 output buffer3803 * 3793 3794 mc1iorec: ds.b IORECLN | MIDI-1 iorec structure 3795 mc2iorec: ds.b IORECLN | MIDI-2 iorec structure 3796 3797 .endc 3798 3799 sr1ibuf: ds.b SR1IBS | Serial-1 input buffer 3800 sr1obuf: ds.b SR1OBS | Serial-1 output buffer 3801 sr2ibuf: ds.b SR2IBS | Serial-2 input buffer 3802 sr2obuf: ds.b SR2OBS | Serial-2 output buffer 3803 3804 3804 .ifne BUCHLA 3805 * 3806 mc1ibuf: ds.b MC1IBS *MIDI-1 input buffer3807 mc1obuf: ds.b MC1OBS *MIDI-1 output buffer3808 mc2ibuf: ds.b MC2IBS *MIDI-2 input buffer3809 mc2obuf: ds.b MC2OBS *MIDI-2 output buffer3810 * 3811 api_inp: ds.b 1 *Analog processor input byte3812 api_bug: ds.b 1 *Analog processor signal # "bug trap"3813 api_sv: ds.b 1 *Analog processor state3814 api_svb: ds.b 1 *Analog processor state "bug trap"3815 * 3805 3806 mc1ibuf: ds.b MC1IBS | MIDI-1 input buffer 3807 mc1obuf: ds.b MC1OBS | MIDI-1 output buffer 3808 mc2ibuf: ds.b MC2IBS | MIDI-2 input buffer 3809 mc2obuf: ds.b MC2OBS | MIDI-2 output buffer 3810 3811 api_inp: ds.b 1 | Analog processor input byte 3812 api_bug: ds.b 1 | Analog processor signal # "bug trap" 3813 api_sv: ds.b 1 | Analog processor state 3814 api_svb: ds.b 1 | Analog processor state "bug trap" 3815 3816 3816 .even 3817 * 3818 api_sig: ds.b 1 *Analog signal number3819 api_val: ds.b 1 *Analog value3820 * 3821 api_fi: ds.l 1 *Analog processor FIFO input pointer3822 api_fo: ds.l 1 *Analog processor FIFO output pointer3823 api_fum: ds.w APISIZE *Analog processor FIFO3824 api_fe .equ * *End of analog processor FIFO3825 * 3826 .endc 3827 * 3817 3818 api_sig: ds.b 1 | Analog signal number 3819 api_val: ds.b 1 | Analog value 3820 3821 api_fi: ds.l 1 | Analog processor FIFO input pointer 3822 api_fo: ds.l 1 | Analog processor FIFO output pointer 3823 api_fum: ds.w APISIZE | Analog processor FIFO 3824 api_fe: | End of analog processor FIFO 3825 3826 .endc 3827 3828 3828 .even 3829 * 3830 basepage: ds.l 64 *Pseudo base page3831 * 3832 buffer: ds.b 1024 *Default disk buffer3833 * 3834 biostop .equ * *End of BIOS RAM3835 * 3829 3830 basepage: ds.l 64 | Pseudo base page 3831 3832 buffer: ds.b 1024 | Default disk buffer 3833 3834 biostop: | End of BIOS RAM 3835 3836 3836 .end -
rom/timeint.s
rf40a309 r4f508e6 1 *------------------------------------------------------------------------------2 *timeint.s -- timer interrupt handler3 *Version 9 -- 1988-06-20 -- D.N. Lynx Crowe4 *------------------------------------------------------------------------------5 * 6 *This code replaces the interrupt handler in bios.s, which is known to7 *have a bug in it, and adds support for the VSDD and an array of programable8 *timers with 1 Ms resolution.9 * 10 *WARNING: There are equates to addresses in the bios EPROM which may change11 *when the bios is reassembled. If the bios is reassembled be sure to update12 *the equates flagged by "<<<=====".13 * 14 *The addresses currently in the equates are for EPROMs dated 1988-04-18 or15 *1988-06-20 ONLY.16 * 17 *------------------------------------------------------------------------------18 *Hardware timer usage:19 *---------------------20 *Timer 1 PLL divider for score clock -- fixed at 6421 *Timer 2 PLL divider for score clock -- nominally 320022 *Timer 3 1 Ms Real Time Clock23 * 24 *------------------------------------------------------------------------------25 * 1 | ------------------------------------------------------------------------------ 2 | timeint.s -- timer interrupt handler 3 | Version 9 -- 1988-06-20 -- D.N. Lynx Crowe 4 | ------------------------------------------------------------------------------ 5 6 | This code replaces the interrupt handler in bios.s, which is known to 7 | have a bug in it, and adds support for the VSDD and an array of programable 8 | timers with 1 Ms resolution. 9 10 | WARNING: There are equates to addresses in the bios EPROM which may change 11 | when the bios is reassembled. If the bios is reassembled be sure to update 12 | the equates flagged by "<<<=====". 13 14 | The addresses currently in the equates are for EPROMs dated 1988-04-18 or 15 | 1988-06-20 ONLY. 16 17 | ------------------------------------------------------------------------------ 18 | Hardware timer usage: 19 | --------------------- 20 | Timer 1 PLL divider for score clock -- fixed at 64 21 | Timer 2 PLL divider for score clock -- nominally 3200 22 | Timer 3 1 Ms Real Time Clock 23 24 | ------------------------------------------------------------------------------ 25 26 26 .text 27 * 28 .xdef _tsetup *tsetup() -- timer setup function29 .xdef timeint *timer interrupt handler30 * 31 .xdef _timers *timer array -- short timers[NTIMERS]32 .xdef _vi_clk *VSDD scroll delay timer33 .xdef _vi_tag *VSDD VI tag34 .xdef line *Line we entered on35 * 36 .xref lclsadr *score object base address37 .xref lclscrl *score object scroll offset38 .xref _v_odtab *VSDD object descriptor table39 .xref _v_regs *VSDD registers40 * 41 .page 42 *==============================================================================43 * 44 *Equates to variables in bios.s:45 *-------------------------------46 *These variables are permanently assigned.47 * 48 TIMEVEC .equ $00000400 *LONG - System timer trap vector49 * 50 FC_SW .equ $00000420 *WORD - Frame clock switch51 FC_VAL .equ $00000422 *LONG - Frame clock value52 * 53 HZ_1K .equ $0000049A *LONG - 1000 Hz clock54 HZ_200 .equ $0000049E *LONG - 200 Hz clock55 FRCLOCK .equ $000004A2 *LONG - 50 Hz clock56 * 57 T3COUNT .equ $000004AA *WORD - Timer 3 count58 * 59 *------------------------------------------------------------------------------60 * 61 *WARNING: The address of "FLOCK" depends on the version of the bios EPROM.62 *The address below is for EPROMs dated 1988-04-18 ONLY.63 * 64 FLOCK .equ $00000E0C *WORD - Floppy semaphore <<<=====65 * 66 *==============================================================================67 * 68 *Equates to routines in bios.s:69 *------------------------------70 * 71 *WARNING: The address of "FLOPVBL" depends on the version of the bios EPROM.72 *The address below is for EPROMs dated 1988-04-18 ONLY.73 * 74 FLOPVBL .equ $001015EE *floppy VI handler address <<<=====75 * 76 *==============================================================================77 * 78 .page 79 * 80 *Hardware address equates:81 *-------------------------82 TI_VEC .equ $00000070 *Timer interrupt autovector83 * 84 TIMER .equ $003A0001 *Timer base address85 * 86 *------------------------------------------------------------------------------87 * 88 *Timer register equates:89 *-----------------------90 TIME_CRX .equ TIMER *Control register 1 or 391 TIME_CR2 .equ TIMER+2 *Control register 292 TIME_T1H .equ TIMER+4 *Timer 1 high byte93 TIME_T1L .equ TIMER+6 *Timer 1 low byte94 TIME_T2H .equ TIMER+8 *Timer 2 high byte95 TIME_T2L .equ TIMER+10 *Timer 2 low byte96 TIME_T3H .equ TIMER+12 *Timer 3 high byte97 TIME_T3L .equ TIMER+14 *Timer 3 low byte98 * 99 *VSDD register offsets:100 *----------------------101 VSDD_R5 .equ 10 *VSDD bank control register102 VSDD_R11 .equ 22 *VSDD access table register103 * 104 *==============================================================================105 * 106 *Miscellaneous equates:107 *----------------------108 IPL7 .equ $0700 *IPL mask for interrupt disable109 * 110 FCMAX .equ $00FFFFFF *Maximum frame counter value111 FCMIN .equ $00000000 *Minimum frame counter value112 * 113 NTIMERS .equ 8 *Number of timers in the timer array114 * 115 *==============================================================================116 * 117 .page 118 *==============================================================================119 *_tsetup -- tsetup() -- timer setup function120 *==============================================================================121 * 122 _tsetup: move.w sr,-(a7) *Save old interrupt mask123 ori.w #IPL7,sr *Disable interrupts124 * 125 clr.w FC_SW *Stop the frame clock126 clr.l FC_VAL *... and reset it127 clr.w _vi_tag *Clear VSDD VI tag128 clr.w _vi_clk *Clear VSDD delay timer129 clr.w lclsadr *Clear score scroll address130 clr.w lclscrl *Clear score scroll offset131 * 132 lea _timers,a0 *Point at timer array133 move.w #NTIMERS-1,d0 *Setup to clear timer array134 * 135 tclr: clr.w (a0)+ *Clear a timer array entry136 dbra d0,tclr *Loop until done137 * 138 move.l #nullrts,TIMEVEC *Set timer interrupt vector139 move.l #timeint,TI_VEC *Set timer trap vector140 * 141 move.b # $00,TIME_T1H *Setup timer 1 (PLL)142 move.b # $1F,TIME_T1L *... for divide by 64143 move.b # $0C,TIME_T2H *Setup timer 2 (FC)144 move.b # $7F,TIME_T2L *... for divide by 3200145 move.b # $03,TIME_T3H *Setup timer 3 (RTC)146 move.b # $20,TIME_T3L *... for 1Ms interval147 move.b # $42,TIME_CRX *Setup CR3148 move.b # $41,TIME_CR2 *Setup CR2149 move.b # $81,TIME_CRX *Setup CR1150 move.b # $80,TIME_CRX *Start the timers151 * 152 move.w (a7)+,sr *Restore interrupts153 * 154 nullrts: rts *Return to caller155 * 156 .page 157 *==============================================================================158 *timeint -- timer interrupt handler159 *==============================================================================160 * 161 timeint: movem.l d0-d7/a0-a6,-(a7) *Save registers162 move.b TIME_CR2,d0 *Get timer interrupt status163 *------------------------------------------------------------------------------164 *process 1 MS timer165 *------------------------------------------------------------------------------166 btst.l #2,d0 *Check timer 3 status167 beq tmi02 *Jump if not active168 * 169 move.b TIME_T3H,d1 *Read timer 3 count170 lsl.w #8,d1 *...171 move.b TIME_T3L,d1 *...172 move.w d1,T3COUNT *... and save it173 * 174 addq.l #1,HZ_1K *Update 1ms clock (1 KHz)175 * 176 move.l d0,-(a7) *Preserve D0177 *------------------------------------------------------------------------------178 *process VSDD timer179 *------------------------------------------------------------------------------180 tst.w _vi_tag *Does the VSDD need service ?181 beq updtime *Jump if not182 * 183 move.w _vi_clk,d0 *Get VSDD scroll delay timer184 subq.w #1,d0 *Decrement timer185 move.w d0,_vi_clk *Update timer186 bne updtime *Jump if it's not zero yet187 * 188 move.w lclsadr,_v_odtab+12 *Update scroll address189 move.w lclscrl,_v_odtab+10 *Update scroll offset190 clr.w _vi_tag *Reset the tag191 * 192 .page 193 * 194 *------------------------------------------------------------------------------195 *process programable timers196 *------------------------------------------------------------------------------197 * 198 updtime: move.w #NTIMERS-1,d0 *Setup timer array counter199 lea _timers,a0 *Point at timer array200 * 201 tdcr: move.w (a0),d1 *Get timer array entry202 beq tdcr1 *Jump if already 0203 * 204 subq.w #1,d1 *Decrement timer205 * 206 tdcr1: move.w d1,(a0)+ *Store updated timer value207 dbra d0,tdcr *Loop until done208 * 209 *------------------------------------------------------------------------------210 *process timer hook vector211 *------------------------------------------------------------------------------212 movea.l TIMEVEC,a0 *Get RTC vector213 move.w #1,-(a7) *Pass 1 msec on stack214 jsr (a0) *Process RTC vector215 addq.l #2,a7 *Clean up stack216 * 217 move.l (a7)+,d0 *Restore D0218 * 219 .page 220 *------------------------------------------------------------------------------221 *process 5 Ms clock222 *------------------------------------------------------------------------------223 move.w tdiv1,d1 *Update divider224 addq.w #1,d1 *...225 move.w d1,tdiv1 *...226 * 227 cmpi.w #5,d1 *Do we need to update HZ_200 ?228 blt tmi02 *Jump if not229 * 230 addq.l #1,HZ_200 *Update 5ms clock (200 Hz)231 *------------------------------------------------------------------------------232 *process 20 Ms floppy clock233 *------------------------------------------------------------------------------234 move.w tdiv2,d1 *Update divider235 addq.w #1,d1 *...236 move.w d1,tdiv2 *...237 * 238 cmpi.w #4,d1 *Do we need to update FRCLOCK ?239 blt tmi01 *Jump if not240 * 241 addq.l #1,FRCLOCK *Update 20 Ms clock (50 Hz)242 tst.w FLOCK *See if floppy is active243 bne tmi00 *Don't call FLOPVBL if so244 * 245 jsr FLOPVBL *Check on the floppy246 * 247 tmi00: move.w #0,tdiv2 *Reset tdiv2248 * 249 tmi01: move.w #0,tdiv1 *Reset tdiv1250 * 251 .page 252 *------------------------------------------------------------------------------253 *process PLL timers254 *------------------------------------------------------------------------------255 * 256 tmi02: btst.l #0,d0 *Check timer 1 int257 beq tmi03 *Jump if not set258 * 259 move.b TIME_T1H,d1 *Read timer 1 to clear int.260 move.b TIME_T1L,d1 *...261 * 262 tmi03: btst.l #1,d0 *Check for timer 2 int.263 beq tmi04 *Jump if not set264 * 265 move.b TIME_T2H,d1 *Read timer 2 to clear int.266 move.b TIME_T2L,d1 *...267 * 268 .page 269 *------------------------------------------------------------------------------270 *update score frame counter271 *------------------------------------------------------------------------------272 tst.w FC_SW *Should we update the frame ?273 beq tmi04 *Jump if not274 * 275 bmi tmi05 *Jump if we count down276 * 277 move.l FC_VAL,d0 *Get the frame count278 cmp.l #FCMAX,d0 *See it we've topped out279 bge tmi06 *Jump if limit was hit280 * 281 addq.l #1,d0 *Count up 1 frame282 move.l d0,FC_VAL *Store updated frame count283 bra tmi04 *Done284 * 285 tmi07: move.l #FCMIN,FC_VAL *Force hard limit, just in case286 bra tmi04 *Done287 * 288 tmi06: move.l #FCMAX,FC_VAL *Force hard limit, just in case289 bra tmi04 *Done290 * 291 tmi05: move.l FC_VAL,d0 *Get the frame count292 ble tmi07 *Done if already counted down293 * 294 subq.l #1,d0 *Count down 1 frame295 move.l d0,FC_VAL *Store udpated frame count296 bra tmi04 *Done297 * 298 nop *Filler to force equal paths299 * 300 tmi04: movem.l (a7)+,d0-d7/a0-a6 *Restore registers301 rte *Return to interrupted code302 * 303 .page 304 *==============================================================================27 28 .xdef _tsetup | tsetup() -- timer setup function 29 .xdef timeint | timer interrupt handler 30 31 .xdef _timers | timer array -- short timers[NTIMERS] 32 .xdef _vi_clk | VSDD scroll delay timer 33 .xdef _vi_tag | VSDD VI tag 34 .xdef line | Line we entered on 35 36 .xref lclsadr | score object base address 37 .xref lclscrl | score object scroll offset 38 .xref _v_odtab | VSDD object descriptor table 39 .xref _v_regs | VSDD registers 40 41 .page 42 | ============================================================================== 43 44 | Equates to variables in bios.s: 45 | ------------------------------- 46 | These variables are permanently assigned. 47 48 TIMEVEC = 0x00000400 | LONG - System timer trap vector 49 50 FC_SW = 0x00000420 | WORD - Frame clock switch 51 FC_VAL = 0x00000422 | LONG - Frame clock value 52 53 HZ_1K = 0x0000049A | LONG - 1000 Hz clock 54 HZ_200 = 0x0000049E | LONG - 200 Hz clock 55 FRCLOCK = 0x000004A2 | LONG - 50 Hz clock 56 57 T3COUNT = 0x000004AA | WORD - Timer 3 count 58 59 | ------------------------------------------------------------------------------ 60 61 | WARNING: The address of "FLOCK" depends on the version of the bios EPROM. 62 | The address below is for EPROMs dated 1988-04-18 ONLY. 63 64 FLOCK = 0x00000E0C | WORD - Floppy semaphore <<<===== 65 66 | ============================================================================== 67 68 | Equates to routines in bios.s: 69 | ------------------------------ 70 71 | WARNING: The address of "FLOPVBL" depends on the version of the bios EPROM. 72 | The address below is for EPROMs dated 1988-04-18 ONLY. 73 74 FLOPVBL = 0x001015EE | floppy VI handler address <<<===== 75 76 | ============================================================================== 77 78 .page 79 80 | Hardware address equates: 81 | ------------------------- 82 TI_VEC = 0x00000070 | Timer interrupt autovector 83 84 TIMER = 0x003A0001 | Timer base address 85 86 | ------------------------------------------------------------------------------ 87 88 | Timer register equates: 89 | ----------------------- 90 TIME_CRX = TIMER | Control register 1 or 3 91 TIME_CR2 = TIMER+2 | Control register 2 92 TIME_T1H = TIMER+4 | Timer 1 high byte 93 TIME_T1L = TIMER+6 | Timer 1 low byte 94 TIME_T2H = TIMER+8 | Timer 2 high byte 95 TIME_T2L = TIMER+10 | Timer 2 low byte 96 TIME_T3H = TIMER+12 | Timer 3 high byte 97 TIME_T3L = TIMER+14 | Timer 3 low byte 98 99 | VSDD register offsets: 100 | ---------------------- 101 VSDD_R5 = 10 | VSDD bank control register 102 VSDD_R11 = 22 | VSDD access table register 103 104 | ============================================================================== 105 106 | Miscellaneous equates: 107 | ---------------------- 108 IPL7 = 0x0700 | IPL mask for interrupt disable 109 110 FCMAX = 0x00FFFFFF | Maximum frame counter value 111 FCMIN = 0x00000000 | Minimum frame counter value 112 113 NTIMERS = 8 | Number of timers in the timer array 114 115 | ============================================================================== 116 117 .page 118 | ============================================================================== 119 | _tsetup -- tsetup() -- timer setup function 120 | ============================================================================== 121 122 _tsetup: move.w sr,-(a7) | Save old interrupt mask 123 ori.w #IPL7,sr | Disable interrupts 124 125 clr.w FC_SW | Stop the frame clock 126 clr.l FC_VAL | ... and reset it 127 clr.w _vi_tag | Clear VSDD VI tag 128 clr.w _vi_clk | Clear VSDD delay timer 129 clr.w lclsadr | Clear score scroll address 130 clr.w lclscrl | Clear score scroll offset 131 132 lea _timers,a0 | Point at timer array 133 move.w #NTIMERS-1,d0 | Setup to clear timer array 134 135 tclr: clr.w (a0)+ | Clear a timer array entry 136 dbra d0,tclr | Loop until done 137 138 move.l #nullrts,TIMEVEC | Set timer interrupt vector 139 move.l #timeint,TI_VEC | Set timer trap vector 140 141 move.b #0x00,TIME_T1H | Setup timer 1 (PLL) 142 move.b #0x1F,TIME_T1L | ... for divide by 64 143 move.b #0x0C,TIME_T2H | Setup timer 2 (FC) 144 move.b #0x7F,TIME_T2L | ... for divide by 3200 145 move.b #0x03,TIME_T3H | Setup timer 3 (RTC) 146 move.b #0x20,TIME_T3L | ... for 1Ms interval 147 move.b #0x42,TIME_CRX | Setup CR3 148 move.b #0x41,TIME_CR2 | Setup CR2 149 move.b #0x81,TIME_CRX | Setup CR1 150 move.b #0x80,TIME_CRX | Start the timers 151 152 move.w (a7)+,sr | Restore interrupts 153 154 nullrts: rts | Return to caller 155 156 .page 157 | ============================================================================== 158 | timeint -- timer interrupt handler 159 | ============================================================================== 160 161 timeint: movem.l d0-d7/a0-a6,-(a7) | Save registers 162 move.b TIME_CR2,d0 | Get timer interrupt status 163 | ------------------------------------------------------------------------------ 164 | process 1 MS timer 165 | ------------------------------------------------------------------------------ 166 btst.l #2,d0 | Check timer 3 status 167 beq tmi02 | Jump if not active 168 169 move.b TIME_T3H,d1 | Read timer 3 count 170 lsl.w #8,d1 | ... 171 move.b TIME_T3L,d1 | ... 172 move.w d1,T3COUNT | ... and save it 173 174 addq.l #1,HZ_1K | Update 1ms clock (1 KHz) 175 176 move.l d0,-(a7) | Preserve D0 177 | ------------------------------------------------------------------------------ 178 | process VSDD timer 179 | ------------------------------------------------------------------------------ 180 tst.w _vi_tag | Does the VSDD need service ? 181 beq updtime | Jump if not 182 183 move.w _vi_clk,d0 | Get VSDD scroll delay timer 184 subq.w #1,d0 | Decrement timer 185 move.w d0,_vi_clk | Update timer 186 bne updtime | Jump if it's not zero yet 187 188 move.w lclsadr,_v_odtab+12 | Update scroll address 189 move.w lclscrl,_v_odtab+10 | Update scroll offset 190 clr.w _vi_tag | Reset the tag 191 192 .page 193 194 | ------------------------------------------------------------------------------ 195 | process programable timers 196 | ------------------------------------------------------------------------------ 197 198 updtime: move.w #NTIMERS-1,d0 | Setup timer array counter 199 lea _timers,a0 | Point at timer array 200 201 tdcr: move.w (a0),d1 | Get timer array entry 202 beq tdcr1 | Jump if already 0 203 204 subq.w #1,d1 | Decrement timer 205 206 tdcr1: move.w d1,(a0)+ | Store updated timer value 207 dbra d0,tdcr | Loop until done 208 209 | ------------------------------------------------------------------------------ 210 | process timer hook vector 211 | ------------------------------------------------------------------------------ 212 movea.l TIMEVEC,a0 | Get RTC vector 213 move.w #1,-(a7) | Pass 1 msec on stack 214 jsr (a0) | Process RTC vector 215 addq.l #2,a7 | Clean up stack 216 217 move.l (a7)+,d0 | Restore D0 218 219 .page 220 | ------------------------------------------------------------------------------ 221 | process 5 Ms clock 222 | ------------------------------------------------------------------------------ 223 move.w tdiv1,d1 | Update divider 224 addq.w #1,d1 | ... 225 move.w d1,tdiv1 | ... 226 227 cmpi.w #5,d1 | Do we need to update HZ_200 ? 228 blt tmi02 | Jump if not 229 230 addq.l #1,HZ_200 | Update 5ms clock (200 Hz) 231 | ------------------------------------------------------------------------------ 232 | process 20 Ms floppy clock 233 | ------------------------------------------------------------------------------ 234 move.w tdiv2,d1 | Update divider 235 addq.w #1,d1 | ... 236 move.w d1,tdiv2 | ... 237 238 cmpi.w #4,d1 | Do we need to update FRCLOCK ? 239 blt tmi01 | Jump if not 240 241 addq.l #1,FRCLOCK | Update 20 Ms clock (50 Hz) 242 tst.w FLOCK | See if floppy is active 243 bne tmi00 | Don't call FLOPVBL if so 244 245 jsr FLOPVBL | Check on the floppy 246 247 tmi00: move.w #0,tdiv2 | Reset tdiv2 248 249 tmi01: move.w #0,tdiv1 | Reset tdiv1 250 251 .page 252 | ------------------------------------------------------------------------------ 253 | process PLL timers 254 | ------------------------------------------------------------------------------ 255 256 tmi02: btst.l #0,d0 | Check timer 1 int 257 beq tmi03 | Jump if not set 258 259 move.b TIME_T1H,d1 | Read timer 1 to clear int. 260 move.b TIME_T1L,d1 | ... 261 262 tmi03: btst.l #1,d0 | Check for timer 2 int. 263 beq tmi04 | Jump if not set 264 265 move.b TIME_T2H,d1 | Read timer 2 to clear int. 266 move.b TIME_T2L,d1 | ... 267 268 .page 269 | ------------------------------------------------------------------------------ 270 | update score frame counter 271 | ------------------------------------------------------------------------------ 272 tst.w FC_SW | Should we update the frame ? 273 beq tmi04 | Jump if not 274 275 bmi tmi05 | Jump if we count down 276 277 move.l FC_VAL,d0 | Get the frame count 278 cmp.l #FCMAX,d0 | See it we've topped out 279 bge tmi06 | Jump if limit was hit 280 281 addq.l #1,d0 | Count up 1 frame 282 move.l d0,FC_VAL | Store updated frame count 283 bra tmi04 | Done 284 285 tmi07: move.l #FCMIN,FC_VAL | Force hard limit, just in case 286 bra tmi04 | Done 287 288 tmi06: move.l #FCMAX,FC_VAL | Force hard limit, just in case 289 bra tmi04 | Done 290 291 tmi05: move.l FC_VAL,d0 | Get the frame count 292 ble tmi07 | Done if already counted down 293 294 subq.l #1,d0 | Count down 1 frame 295 move.l d0,FC_VAL | Store udpated frame count 296 bra tmi04 | Done 297 298 nop | Filler to force equal paths 299 300 tmi04: movem.l (a7)+,d0-d7/a0-a6 | Restore registers 301 rte | Return to interrupted code 302 303 .page 304 | ============================================================================== 305 305 .bss 306 *==============================================================================307 * 308 *A note on tdiv1 and tdiv2:309 *--------------------------310 * 311 *tdiv1 and tdiv2 are actually defined in the bios, but since they could move312 *we define them here and ignore the ones in the bios.313 * 314 tdiv1: ds.w 1 *Timer divider 1 (divides HZ_1K)315 tdiv2: ds.w 1 *Timer divider 2 (divides HZ_200)316 * 317 *------------------------------------------------------------------------------318 * 319 _timers: ds.w NTIMERS *Timer array -- short timers[16];320 * 321 _vi_clk: ds.w 1 *VSDD scroll delay timer322 _vi_tag: ds.w 1 *VSDD VI 'needs service' tag323 * 324 bank: ds.w 1 *VSDD bank we enterd with325 line: ds.w 1 *Line we came in on (for analysis)326 *==============================================================================327 * 306 | ============================================================================== 307 308 | A note on tdiv1 and tdiv2: 309 | -------------------------- 310 311 | tdiv1 and tdiv2 are actually defined in the bios, but since they could move 312 | we define them here and ignore the ones in the bios. 313 314 tdiv1: ds.w 1 | Timer divider 1 (divides HZ_1K) 315 tdiv2: ds.w 1 | Timer divider 2 (divides HZ_200) 316 317 | ------------------------------------------------------------------------------ 318 319 _timers: ds.w NTIMERS | Timer array -- short timers[16]; 320 321 _vi_clk: ds.w 1 | VSDD scroll delay timer 322 _vi_tag: ds.w 1 | VSDD VI 'needs service' tag 323 324 bank: ds.w 1 | VSDD bank we enterd with 325 line: ds.w 1 | Line we came in on (for analysis) 326 | ============================================================================== 327 328 328 .end
Note:
See TracChangeset
for help on using the changeset viewer.