-
Notifications
You must be signed in to change notification settings - Fork 0
/
TODO
834 lines (760 loc) · 23.2 KB
/
TODO
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
- prism BIOS +
- set internal interrupts +
- main app writes indexes of storages in main mem, BIOS reads them +
- set correct modes to peripheral +
- start bootloader +
- test timers/video/keyboard +
- initial CPU test
- find bootable media
- Debug infra +
- Logger in CPU monad +
- Needs to be disabled when not needed without changing the code +
- Write logs to file +
- Trace jumps +
- Trace interrupts +
- Trace BIOS calls +
- Logger in peripherals +
- Reorder log config +
- Print additional info
- date +
- feature +
- severity level +
- instruction num
- location
[date] [level] [feature] -- msg
- Testing infra +
- Create custom code which runs in QEMU +
- Compare values in memory after the test +
- Use QEMU as a backend to compare results +
- Find how to run arbitrary binary in QEMU +
- -device loader
- qemu-system-i386 -drive file=boot.img,index=0,media=disk,format=raw -boot c -net none +
- create bootable FD image +
- create prologue which loads test body and intializes registers. Starts at 0x7C00
- test body will be loaded at 0x8000 address
- at 0x7E00 there will be area for dumped registers
- test will be jump to epilogue
- epilogue will be just after prologue (hlt between them)
- epilogue will dump all registers and flags to "dump area"
- epilogue will write magic value to specific location
- epilogue will end wilh loop of hlt
- Find if it is possible to get QEMU memory after execution +
- -m 1M -object memory-backend-file,id=pc.ram,size=1M,mem-path=mem.data,prealloc=on,share=on -machine memory-backend=pc.ram +
- https://wiki.qemu.org/Documentation/QMP
- memsave
{ 'command': 'memsave',
'data': {'val': 'int', 'size': 'int', 'filename': 'str', '*cpu-index': 'int'} }
- -qmp tcp:localhost:4444,server,wait=off
- Test sequence +
- make bootable image +
- take into account that qemu may not be able to detect FD type +
- boot sectors will always be 512 bytes +
- but tracks might be arbitrary big +
- make two types of test application +
- one to run in prism +
- second to run at qemu +
- start qemu +
- wait until qemu finishes running test +
- wait 500ms +
- alternative is to implement TCP client(JSON API) which periodically checks magic number in qemu
- stop qemu via "kill 15" +
- alternative is to stop it via JSON API
- read test memory area + dump area from RAM file +
- alternative is to read memory directly from qemu via JSON API
- Bulk tests
- Allow to test multiple conditions in a single test
- Test body will be generated by test infra
- existing operand manipulation infra could be reused to create tests
- readOp/writeOp may be used to create corresponding asm lines
- what to do with reg-reg ops?
- Results will be written to output memory
- Peripherals
- Remove local/remote from infra
- Separation will be handled inside of peripherals impl
- Use CpuMonad for peripherals actions
- Or at least simplify it
- New decoder and command system
- Implement readOp/writeOp for flags
- Cleanup
- Remove halt printing from hlt command +
- Create correct features for logging +
- Remove commented lines +
- Update lib versions +
- Log updates +
- Release
- LICENSE +
- Move script to another dir +
- Move sample ASM to another dir +
- Create script for bochs +
- README +
- General description
- 16 bit emulation
- ASM tests
- Exmaple
- Run FreeDOS
- Debug
- GDB
- Logs
- Limitations
- Only floppy
- Only PC BIOS
- No graphics
- No sound
- No direct video memory writes
- Tested only on LE (need to check BE)
-------------------------------------------------------
Bulk test:
makeTestIter1 specOp dest op val valN flagsVal = do
writeFlags flagsVal
writeOp op val
specOp op valN
writeOp (Mem dest) op
writeOp (Mem $ dest + 2) flags
makeTestIter2 specOp dest op op2 val val2 valN flagsVal = do
writeFlags flagsVal
writeOp op val
writeOp op2 val2
specOp op op2 valN
writeOp (Mem dest) op
writeOp (Mem $ dest + 2) flags
makeTestPerm1 specOp dest ops vals flagsL =
mapM_ (\op val flags dest -> makeTestIter1 specOp dest op val valN flags) ...
-------------------------------------------------------
ELKS
- Enable CONFIG_CONSOLE_BIOS to use BIOS console
- Direct console manipulates memory directly, without BIOS
- To make it work need to implement memory handles for video MEM
-------------------------------------------------------
PIT command 0xb6
- Timer2
- RW both
- mode 3
- format 0
-------------------------------------------------------
p ($ds * 16 + $di)
print /s (char*)($ds * 16 + $si)
print /s (char*)($es * 16 + $di)
repz cmps byte ptr ds:[si], byte ptr es:[di]
if "%_CWD%" == "%%i:\" set DOSDRV=%%i:
%%i
Test instructions:
- das
- aas
- daa
- aad
- aam
BCD
- unsigned packed decimal
- two digits per-byte
- supports addition and subtraction
- range: 0-99
- example:
- 0x07 -> 7 (valid)
- 0x89 -> 89 (valid)
- 0xC1 -> * (invalid)
- unsigned unpacked decimal
- one digit per-byte
- supports addition, subtraction, multiplication and division
- range: 0-9
- example:
- 0x07 -> 7 (valid)
- 0x89 -> * (invalid)
- 0xC1 -> * (invalid)
AAA - ASCII adjust for addition
DAA - decimal adjust for addition
AAS - ASCII adjust for subtraction
DAS - decimal adjust for subtraction
AAM - ASCII adjust for mutiply
AAD - ASCII adjust for division
Strings are interruptible
CX - counter
DF - direction
ZF - scan/compare terminator
rep - repeat while not end-of-string
movs, stos
is prefix
repe/repz - same a rep
cmps, scas
reads ZF which is set by cmps or scas
ZF must be set to continue repetition
repne/repnz - same as repe/repz
ZF must be cleared to continue repetition
movs - copies byte/word from source (SI) to dest (DI)
increments SI and DI
used to copy data from memory to memory
movsb/movsw - same as movs
cmps - subtracts val addresses by DI from val addresses by SI
increments SI and DI
updates flags
maybe combined with repX or used with conditional jumps
used to match strings
scas - subtracts val addresses by DI from context of AL/AX
increments DI
updates flags
used to find element in string
lods - copy val addresses by SI to AL/AX
increments SI
not used with repX
stos - copy val from AL/AX to place addresses by DI
increments DI
used to initialize string
check segment override prefix
-------------------------------------------------------
radare2 -e asm.bits=16 x86BOOT.img
1.474.560
-------------------------------------------------------
- peripheral
- PPI (8255A)
- keyboard (XT style)
- video
- DMA (intel 8237)
- floppy
- HDD
- CMOS
- later
- keyboard (8042)
-------------------------------------------------------
HSBIOS
- Simple implementation of PC BIOS
- Completely in haskell
- Will not use "real" peripherals
Memory addresses
- 0 - 0x3ff - interrupt vectors
- 0x400 - 0x500 - BIOS DATA
- 0x7C00 - Boot sector (start for user code)
- 0xE0000 - 0xFFFFF - BIOS ROM
- 0xFFFF0 - 8086 start instruction
BIOS RAM area
- 0x0-0x7 - 4 serial ports
- 0x8-0xf - 4 parallel ports
- 0x10-0x11 - installed devices (int 0x11)
- 0x12 - POST
- 0x13-0x14 - installed memory in KB
- 0x15-0x16 - POST
- 0x17 - keyboard shift flags
- 0x18 - keyboard ext shift flags
- 0x19 - alt key + numeric keypad
- 0x1A-0x1B - pointer to next char in keyboard buffer
- 0x1C-0x1D - pointer to first spot in keyboard buffer
- 0x1E - 16w keyboard buffer
- 0x3E - diskette recalibrate status
- 0x3F - diskette motor status
- 0x40 - diskette motor timeout
- 0x41 - diskette return code
- 0x42-0x48 - diskette controller status
- 0x49 - video mode setting
- 0x4A - number of columns on screen
- 0x4C - current page size (video)
- 0x4E - current page address (video)
- 0x50 - cursor pos on each page (8 pages)
- 0x60 - cursor type
- 0x62 - current page number (video)
- 0x63 - io port video
- 0x65 - current mode selector reg
- 0x66 - current palette value
- 0x67-0x6A - POST
- 0x6B - POST
- 0x6C - timer count
- 0x70 - 24h rollover flag
- 0x71 - ctrl-break flag
- 0x72 - POST
- 0x74 - status from last hdd operation
- 0x75 - number of hdds
- 0x76 - hdd control byte
- 0x77 - hdd port offset
- 0x78 - printer timeout table
- 0x7C - serial timeout table
- 0x80 - offset to start of keyboard buffer(from seg 0x40)
- 0x82 - offset to end of keyboard buffer
- 0x84 - number of rows on screen
- 0x85 - char height (VGA)
- 0x87 - VGA
- 0x88 - VGA
- 0x89 - VGA
- 0x8A - VGA
- 0x8B - diskette rate
- 0x8C - hdd status
- 0x8D - hdd error
- 0x8E - hdd interrupt flag
- 0x8F - diskette controller info
- 0x90-0x91 - media type of both drives
- 0x92 - diskette driver service area
- 0x94 - current track number
- 0x96 - keyboard status byte
- 0x97 - keyboard LED status
- 0x98 - user wait flag offset address
- 0x9A - user wait flag segment address
- 0x9C - LSB of wait count
- 0x9E - MSB of wait count
- 0xA0 - wait active flag
- 0xA8 - VGA
- 0xB0-0xB5 - reserved
- 0xB6-0xB8 - POST
- 0xC0-0xCD - reserved
- 0xCE - count of days since 1980
- 0xCF-0xFF - reserved
- 0x100 - print screen status bytes
CHS
A = (c * N_heads + h) * N_sectors + (s - 1)
CMOS for diskette
0x10 bits 7-4 drive 0 type (0x4 - 1.44)
bits 3-0 drive 1 type (0x4 - 1.44)
Diskette parameters table 0x1E
0x00 - bits 7-4 drive type/transfer rate -> 0xd0
bits 3-0 head unload time -> 0x0f
0x01 - bits 7-1 head load time -> 0x02
bit 0 non-DMA flag -> 0x00
0x02 - motor turn-off delay -> 0x25
0x03 - bytes per sector -> 0x02 (512)
0x04 - sectors per track -> 0x18 (18)
0x05 - gap length -> 0x1B
0x06 - data length -> 0xff
0x07 - gap length for format -> 0x6c
0x08 - fill byte for format -> 0xF6
0x09 - head settle time -> 0x0F
0x0A - motor start time -> 0x08
HDD parameters table 0x41(0x46 for driver 1)
0x00 - number of cylinders (2 bytes)
0x02 - number of heads
0x03 - reserved (2 bytes) -> 0
0x05 - starting write precompensation cylinder (2 bytes) -> 0
0x07 - reserved -> 0
0x08 - control byte -> 0xC0
0x09 - reserved (3 bytes) -> 0
0x0C - landing zone cylinder (2 bytes) -> 0
0x0E - number of sectors per track
0x0F - reserved -> 0
Functions
- int 8 (Timer) - BIOS internal (ISR)
- int 9 (Keyboard) - BIOS internal (ISR)
- int 0x10 (Video)
- ah 0 (Set video mode)
- al 0-7, d-13
- out al
0x20 when mode > 7
0x30 when mode 0-5 or 7
0x3f when mode 6
- ah 1 (Set cursor shape)
- ch - bit 5 disable cursor, 4-0 top scan line
- cl - bit 6-5 show cursor, 4-0 low scan line
-- (0,25) means to hide cursor
- ah 2 (Set cursor pos)
- bh - display page number
- dh - row
- dl - column
- out al = 0
- ah 3 (Get cursor pos)
- bh page number
- out ax = 0
- ch starting cursor scan line
- cl ending cursor scan line
- dh row number
- dl column number
- ah 6 (Scroll up)
- al scroll distance in rows
- bh attr for blank lines
- ch top row scroll window
- cl left column scroll window
- dh bottom row scroll window
- dl right column scroll window
- ah 7 (Scroll down)
- ah 8 (Get char)
- bh page
- out ah attr
- al char
- ah 9 (Write char + attr)
- al ascii char
- bh page
- bl attr
- cx repeat count
- ah e (Write char)
- al ascii char
- bl color fg
- bh page
- ah f (Get video mode)
- out ah number of columns
- al mode
- bh active page
- int 0x11 (Get equipment)
- Output to AX
- Bits 15 - 14 - number of printers
- Bits 13 - 12 - reserved
- Bits 11 - 9 - number of serial ports
- Bits 8 - reserved
- Bits 7 - 6 - number diskettes
- 00 - 1 diskette
- 01 - 2 diskettes
- Bits 5 - 4 - video mode
- 00 - VGA/EGA/PGA
- 01 - 40x25 color
- 10 - 80x25 color
- 11 - 80x25 mono
- Bit 3 - reserved
- Bit 2 - pointing device
- Bit 1 - math coprocessor
- Bit 0 - diskette for boot
- int 0x12 (Get memory size)
- Output to AX
- int 0x13 (Disk)
- ah 0 (Reset disk) -
- ah 1 (Read status) -
- ah 2 (Read sectors)
- al - number of sectors
- ch - track number
- cl - sector number
- dh - head number
- dl - driver number (0x80 for hdd)
- es:bx - pointer to buffer
- out al - sectors read
- ah 3 (Write sectors)
- same as read
- ah 4 (Verify sectors)
- ah 5 (Format track)
- ah 8 (Read params)
- dl - drive number
- out for diskette
- ax - 0 -- always 0
- bh - 0 -- always 0
- bl - 04 (3.5", 1.44 MB)
- ch - tracks
- cl - sectors
- dh - heads, always 1 when CMOS valid
- dl - number of diskette drives
- es:di - pointer to param table
- CF = 0 when no error
- out for HDD
- ah - 0 when valid
7 when drive number is invalid
- al - always 0
- ch - cylinder lower 8 bits, zero-based, 00 when ah == 7
- cl - bits 0-5 sectors
bits 6-7 cylinder high 2 bits (00 when ah == 7)
- dh - heads
- dl - number of drives, zero-base, 00 when ah == 7
- es:di - pointer to param table
- CF = 0 when no error
- ah c (Seek)
- ah 10 (Check ready)
- ah 15 (Read type)
- dl - driver number
- out
for HDD
- ah - 03 fixed disk
- cx - high bits of sectors number per-disk
- dx - low bits of sectors number per-disk
- ah 16 (Detect media change)
- int 0x14 (Serial)
- int 0x15 (System services)
- int 0x16 (Keyboard) (DSR)
- ah 0 (Get key)
- Return 2 byte key in AX
- AH contains Scan code
- AL contains ASCII code
- Remove key from buffer
- When buffer is empty - suspend
- ah 1 (Return keyboard status)
- Return 2 byte key in AX
- Key is not removed from buffer
- If buffer is empty ZF=1
- If buffer is not empty ZF=0
- ah 2 (Return shift flag status)
- AL contains flags
- Bit 7 - Insert
- Bit 6 - Caps Lock
- Bit 5 - Num Lock
- Bit 4 - Scroll Lock
- Bit 3 - Alt pressed
- Bit 2 - Ctrl pressed
- Bit 1 - Left Shift pressed
- Bit 0 - Right Shift pressed
- ah 0x12 (Return extended shift flag status)
- AL contains same flags as AH 2
- AH contains flags
- Bit 7 - SysReq pressed
- Bit 6 - Caps Lock
- Bit 5 - Num Lock
- Bit 4 - Scroll Lock
- Bit 3 - Right Alt
- Bit 2 - Right Ctrl
- Bit 1 - Left Alt
- Bit 0 - Left Ctrl
- int 0x17 (Printer)
- int 0x19 (Reboot)
- Loads 512 bytes from storage to 0x7C00 and transferres control
- int 0x1a (Clock)
- ah 0 (Read System Timer Time Counter)
Ticks are 18.2 Hz
- al - Timer overflow (0 when < 24h since boot)
- CF (1 - error)
- CX - High word ticks
- DX - Low word ticks
- ah 2 (Read Real Time Clock Time)
- AL - Hours BCD
- CF - 0 = clock operating
- CH - Hours BCD
- CL - Minutes BCD
- DH - Seconds BCD
- DL - Daylight saving time
- ah 4 (Read Real Time Clock Date)
- CF - 1 = update in progress
- CH - Century in BCD (19 or 20)
- CL - Year in BCD
- DH - Month in BCD
- DL - Day in BCD
- int 0x1b (Break code)
- int 0x1d (Video params)
- int 0x1e (Disk params)
Communication types:
- Peripheral -> CPU
- Keyboard
- Generates interrupts
- Sends key make-break
- Sends key code
- Serial
- Printer
- CPU -> Peripheral
- Video
- Set/Get cursor
- Set/Get video mode
- Write/Get char
- Disk
- Serial
- Printer
- CPU -> CPU
- Timer
- Clock
- Reboot
- Static return
- Memory size
- Equipment
- Video params
- Disk params
Keyboard implementation
- Set interrupt for keyboard IRQs
- Make thread-safe keyboard state
- Share state between CPU and peripheral thread
- Upon receiving interrupt read keyboard shared state
- Generate internal interrupts
Keyboard
- Shift/Toggle keys: Shift, Alt, Ctrl, Caps Lock, Num Lock, Scroll Lock
- Each "key" consists of two bytes: main and aux
- Some keys have special function:
- Ctrl-Alt-Del - System reset
- Ctrl-Break - Break
- Ctrl-NumLock - Pause
- Shift-PrintScreen - Print screen
- SysReq - System request
Video implementation
- Spawn peripheral thread
- Create shared video state
- Each 30ms draw video frame
- Check shared state before drawing
- Shared state will have info about video updates (if video memory was updated since last screen draw)
- CPU will update shared state when it touches video memory
Disk implementation
- Read/Write file in CPU context
- Hardcode default disk parameters
- Use raw disk image of a default size
Timer implementation
- Use CPU scheduler or PIT to create timer
- Call BIOS function for each timer event
- From BIOS call corresponding user interrupt
Clock implementation
- Use base lib to read and convert current date
- Ticks could be read from run-time
Static parameters
- Will be hardcoded or defined via arguments
HW ports
- Need PIC/PIT
- Video cursor
- Video resolution
- Video scancode/refresh
Video char attributes:
Blink enabled:
- Bit 7 - foreground blinks
- Bit 6-4 - background color
- Bit 3-0 - foreground color
Blink disabled:
- Bit 7-4 - background color
- Bit 3-0 - foreground color
Colors:
- 0 - black
- 1 - blue
- 2 - green
- 3 - cyan
- 4 - red
- 5 - magenta
- 6 - brown
- 7 - white
- 8 - gray
- 9 - bright blue
- 10 - bright greep
- 11 - bright cyan
- 12 - bright red
- 13 - bright magenta
- 14 - yellow
- 15 - bright white
TODO:
- Implement BIOS structs +
- Create keyboard infra +
- Implement basic keyboard functions
- Internal interrupt +
- Char conversion
- 0, 1, 2, 12 +
- Implement BIOS tests (part of test-asm) +
- Send keyboard interrupts + update shared state +
- Implement BIOS timer +
- Static parameters +
- Hardcode default +
- Create unit tests +
- Implement basic video functions +
- Implement simple application which uses BIOS +
- Key echo (read key, write key) +
- Implement BIOS disk/floppy +
- Disk functions in main app +
- Implement test app which has bootloader area +
- Halt for BIOS data memory +
- Correct scroll code +
- Key conversion +
- Implement bootloader logic in BIOS
-------------------------------------------------------
BIOS
data Key = Key {
}
data BiosKeyboard = BiosKeyboard {
remoteKeyboardState :: SharedKeyboardState,
keyList :: [Key],
}
data BiosState = BiosState {
biosKeyboard :: BiosKeyboard,
}
class DirectCommandPeripheral m where
directCommand :: DirectCommand -> m ()
-------------------------------------------------------
PIC
- IRR - input interrupts which are active
- ISR - serviced interrupts
- IMR - masked interrupts
ICW1
- LTIM (Level trigger mode)
- 1 - Level
- 0 - Edge
- ADI (Call address interval)
- 1 - 4
- 0 - 8
- SNGL
- 1 - single
- 0 - cascade
- IC4
- 1 - ICW4 needed
- 0 - no ICW4 needed
ICW2 (interrupt address)
- bits 3-7 -> T3-T7
ICW3 (cascade config)
- S0-S7 - 1 has slave (master)
- ID0-ID2 - id (slave)
ICW4
- SFNM (speciall fully nested mode)
- 1 - yes
- BUF
- 1 - yes
- M/S (works only in BUF mode)
- 1 - master
- 0 - slave
- AEOI (automatic end of interrupt)
- 1 - yes
- uPM (microprocessor mode)
- 0 - 80/85
- 1 - 8086
OCW1 (configure IMR)
- 1 - mask (disable interrupt)
- 0 - unmask (enable interrupt)
OCW2
- R (rotate)
- 1 - yes
- SL (specific)
- 1 - yes
- EOI (end of interrupt)
- 1 - EOI
- 0 - AEOI
- L (interrupt level)
- 3 bits
OCW3
- RIS
- RR
- 11 - Read IS
- 01 - Read IR
- P (poll)
- 1 - poll command
- SMM
- ESMM
- 11 - set special mask
- 01 - reset special mask
-------------------------------------------------------
actions
- config
- can trigger interrupt and scheduling actions
- raise/lower interrupt
- out pin status will be used to set PIC
- schedule update
- may trigger rescheduling
- may trigger interrupt
- write status/counter
- may cause interrupts or scheduling
- read status/counter
- read does not cause actions
- set gate
- can trigger interrupt and scheduling
- all actions require actual CPU cycles
- CPU cycles always increment
- CPU cycles never goes backwards
read-write
- totally independent state and buffers for read (OL) and write (CR)
- for multi bytes write it must be accumulated before set to CE
read commands
- direct read from latches, latches follow CE
- counter will be read directly according RW mode configured with controll command
- second latch may go increment while first one is read
- latch counter and then read latches
- read back command
latch (OL) is held until
- it is read
- counter is reprogrammed
- writing new counter values does not cause clear of OL
- only control word applied to counter causes it
latch is per-counter
second latch command is ignored, first is held until it is read
read-back generates special output
-
can latch multiple counters, same action as latch command
when status and count latched, then first read value is status
counter components:
- preset (Uint16), value written to counter (CR)
- CR state
- null count
- CPU cycles when counting started
- will be used when counter is read to emulate pulses
- latch for status
- read state
- read latch (OL)
- write state
- write latch (CR)
- mode (0-5)
- count format (BIN/BCD)
- out pin (1/0)
0x40 - timer 0
0x41 - timer 1
0x42 - timer 2
0x43 - code word
- only write
- no read
0x61 - speaker (out pin?)
-------------------------------------------------------
class DebugLevel l where
debugLevelEnabled :: l -> Bool
debugLevelName :: l -> String
debugLevelNameT :: l -> Text
class (Monad m) => CpuDebug d m where
cpuDebugLog :: (DebugLevel l) => d -> l -> String -> m ()
cpuDebugAction :: (DebugLevel l) => d -> l -> m () -> m ()
-------------------------------------------------------