Updated the 5170 BIOS map, updated 8042 info, fixed some 8042 controller commands, made HLT work, and fixed the debugger's history buffer when executing a mix of real-mode and protected-mode instructions

This commit is contained in:
Jeff Parsons 2014-10-01 17:33:17 -07:00 committed by jeffpar
commit 93b81c47b7
13 changed files with 804 additions and 287 deletions

File diff suppressed because one or more lines are too long

View file

@ -1,8 +1,24 @@
F000:002C @ POST1
F000:00A6 @ POST1_TEST01 ; TEST.01: 286 PROCESSOR TEST (REAL MODE)
F000:01EE @ POST1_TEST02 ; TEST.02: VERIFY CMOS SHUTDOWN BYTE
F000:0213 @ POST1_TEST03 ; TEST.03: ROS CHECKSUM TEST
F000:0225 @ POST1_TEST04 ; TEST.04: 8253 CHECK TIMER 1 (ALL BITS ON)
F000:025C @ POST1_TEST05 ; TEST.05: 8253 CHECK TIMER 1 (ALL BITS OFF)
F000:027B @ POST1_TEST06 ; TEST.06: 8237 DMA 0 INITIALIZATION
F000:02C6 @ POST1_TEST07 ; TEST.07: 8237 DMA 1 INITIALIZATION
F000:033B @ POST1_TEST08 ; TEST.08: DMA PAGE REGISTER TEST
F000:038E @ POST1_TEST09 ; TEST.09: STORAGE REFRESH TEST
F000:03A6 @ POST1_TEST10 ; TEST.10: 8042 TESTS
F000:03DD @ POST1_GETSW ; GET SWITCH SETTINGS
F000:0426 @ POST1_TEST11 ; TEST.11: BASE 64K R/W STORAGE TEST
F000:0606 @ POST1_SETMFG ; SET MFG_TST
F000:060D @ POST1_TEST11A ; TEST.11A: VERIFY GDT/IDT INSTRUCTIONS
F000:06FA @ POST1_TEST12 ; TEST.12: VERIFY CMOS CHECKSUM
F000:07E2 @ POST1_TEST13 ; TEST.13: PROTECTED MODE TEST
F000:08B7 @ POST1_TEST13A ; TEST.13A: MEMORY SIZE TEST (ABOVE 1024K)
F000:0AB4 @ POST1_TEST14 ; TEST.14: INITIALIZE CRT CONTROLLER
F000:0B27 @ POST1_TEST15 ; TEST.15: VIDEO LINE TEST
F000:0B37 @ POST1_TEST16 ; TEST.16: CRT INTERFACE LINES TEST
0C3F +
F000:0000 @ POST2 ; TEST.17: 8259 PIC TEST
F000:0058 @ POST2_CP27 ; CHECKPOINT 0x27

View file

@ -1,4 +1,4 @@
From [http://minuszerodegrees.net/bios/BIOS_5170_10JAN84_6MHZ/README.TXT](http://minuszerodegrees.net/bios/BIOS_5170_10JAN84_6MHZ.zip):
From [http://minuszerodegrees.net/bios/BIOS_5170_10JAN84_6MHZ/README.TXT](http://minuszerodegrees.net/bios/):
This is the first BIOS for the IBM 5170.
It is dated 10JAN84.
@ -9,7 +9,7 @@ From [http://minuszerodegrees.net/bios/BIOS_5170_10JAN84_6MHZ/README.TXT](http:/
8 bit checksum of 6181028 = 36
8 bit checksum of 6181029 = CA
----
--
added = 00
There are two BIN files in this ZIP file:
@ -17,14 +17,17 @@ From [http://minuszerodegrees.net/bios/BIOS_5170_10JAN84_6MHZ/README.TXT](http:/
1. BIOS_5170_10JAN84_U27_6181028_27256_6MHZ.BIN --> Use this to create a U27 using a 27256 EPROM (rated at 150nS or faster)
2. BIOS_5170_10JAN84_U47_6181029_27256_6MHZ.BIN --> Use this to create a U47 using a 27256 EPROM (rated at 150nS or faster)
The JSON-encoded ROM image that PCjs uses ([1984-01-10.json]()) was created using the *FileDump* command-line *merge* option:
The JSON-encoded ROM image that PCjs uses was created using the *FileDump* command-line *merge* option:
filedump --file=BIOS_5170_10JAN84_U27_6181028_27256_6MHZ.BIN --merge=BIOS_5170_10JAN84_U47_6181029_27256_6MHZ.BIN --output=1984-01-10.json
filedump --file=http://static.pcjs.org/devices/pc/bios/5170/BIOS_5170_10JAN84_U27_6181028_27256_6MHZ.BIN --merge=http://static.pcjs.org/devices/pc/bios/5170/BIOS_5170_10JAN84_U47_6181029_27256_6MHZ.BIN --output=1984-01-10.json --overwrite
Since a MAP file ([1984-01-10.map]()) exists as well, it is automatically appended to the JSON file ([1984-01-10.json]())
when using a ROM input file (or JSON output file) with a matching filename.
Similarly, to create a binary ROM image (1984-01-10.rom), add *--format=rom* to the command-line. These operations can
only be performed using the *FileDump* command-line interface; the *FileDump* API does not support the *merge* option.
It is also possible to create a merged binary ROM image ([1984-01-10.rom](http://static.pcjs.org/devices/pc/bios/5170/1984-01-10.rom))
by adding *--format=rom* to the command-line (the default is *--format=json*).
A MAP file [1984-01-10.map]() exists as well, which is automatically appended to the JSON file when using a ROM input
file (or JSON output file) with a matching filename. For example:
These operations can only be performed using the *FileDump* command-line interface; the *FileDump* API does not support
either the *merge* option or the appending of MAP data. For the moment, the API can only dump unadorned ROM images; eg:
http://www.pcjs.org/api/v1/dump/?file=/devices/pc/bios/5170/1984-01-10.rom
http://www.pcjs.org/api/v1/dump/?file=http://static.pcjs.org/devices/pc/bios/5170/1984-01-10.rom

View file

@ -0,0 +1,10 @@
8042 Keyboard Controller Internals
---
The following documents were obtained from [halicery.com](http://halicery.com/):
- [8042_INTERN.TXT]()
- [8042_1503033.TXT]()
- [dasm42.c]()
Additional information (eg, undocumented 8042 commands) is also available from [OS/2 Museum](http://www.os2museum.com/wp/?p=589).

View file

@ -0,0 +1,408 @@
#include <stdio.h> // we use printf()
/*
Small Intel UPI-41/42 DISASSEMBLER
==================================
A. Tarpai 2010 (tarpai76 gmail com)
It was written to look at some 8042 ROM dump code.
You can use and modify it for any purpose.
I'm happy if you mention me, the author.
No warranties (what for?).
Usage:
------
Call dasm42() passing a pointer, an offset and number of bytes.
Uses 1 external: printf().
The disassembler is based on the book
"Microprocessor Peripherals UPI-41A/41AH/42/42AH User's Manual, INTEL CORPORATION, 1996"
*/
static int PC;
/* Operand Addressing Mode writers */
typedef void (*Tfop)(unsigned char *p);
static void fopJMP(unsigned char *p) // JMP and CALL: 11-bit absolute address (2K)
{
printf("$%04X", ((*p<<3)&0x700) | p[1]);
}
static void fopJ(unsigned char *p) // jumps: 8-bit in-page address
{
printf("$%04X", (PC&0xff00)|p[1]); // TODO!! Jump at page boundary?? PC or PC+2 here?
}
static void fopRx(unsigned char *p) // Register Direct (x=0-7)
{
printf("R%x", *p&7);
}
static void fopPx(unsigned char *p) // Port Direct (x=[1,2])
{
printf("P%x", *p&3);
}
static void fopRRx(unsigned char *p) // Indexed @R0 or @R1
{
printf("@R%x", *p&1);
}
static void fopA(unsigned char *p) // Accumulator
{
printf("A");
}
static void fopIMM(unsigned char *p) // Immediate 8-bit value
{
printf("#$%02X", p[1]);
}
typedef void (*Tfmnop)(unsigned char *p, Tfop fop1, Tfop fop2);
static void fopJB(unsigned char *p, Tfop fop1, Tfop fop2) // JBx is special (have to complete the mn)
{
printf("%x ", *p>>5);
fopJ(p);
}
static void fmnop2(unsigned char *p, Tfop fop1, Tfop fop2) // 2-operand instructions
{
printf(" ");
fop1(p);
printf(",");
fop2(p);
}
static void fmnop1(unsigned char *p, Tfop fop1, Tfop fop2) // 1-operand instructions
{
printf(" ");
fop1(p);
}
struct instr {
char *mn;
unsigned char opcd;
unsigned char opcdmsk;
char len;
Tfmnop fmnop;
Tfop fop1, fop2;
};
static struct instr instrs[] = {
{ "ADD", 0x68, 0xf8, 1, fmnop2, fopA, fopRx}, // ADD A,Rr Add Register Contents to Accumulator
{ "ADD", 0x60, 0xfe, 1, fmnop2, fopA, fopRRx}, // ADD A,@Rr Add Data Memory Contents to Accumulator
{ "ADD", 0x03, 0xff, 2, fmnop2, fopA, fopIMM}, // ADD A,Ýdata Add Immediate Data to Accumulator
{ "ADDC", 0x78, 0xf8, 1, fmnop2, fopA, fopRx}, // ADDC A,Rr Add Carry and Register Contents to Accumulator
{ "ADDC", 0x70, 0xfe, 1, fmnop2, fopA, fopRRx}, // ADDC A,@Rr Add Carry and Data Memory Contents to Accumulator
{ "ADDC", 0x13, 0xff, 2, fmnop2, fopA, fopIMM}, // Add Carry and Immediate Data to Accumulator
{ "ANL", 0x58, 0xf8, 1, fmnop2, fopA, fopRx}, // AND A,Rr Add Register Contents to Accumulator
{ "ANL", 0x50, 0xfe, 1, fmnop2, fopA, fopRRx}, // AND A,@Rr Add Data Memory Contents to Accumulator
{ "ANL", 0x53, 0xff, 2, fmnop2, fopA, fopIMM}, // AND A,Ýdata Add Immediate Data to Accumulator
{ "ANL", 0x98, 0xfc, 2, fmnop2, fopPx, fopIMM}, // ANL PP,Ýdata Logical AND PORT 1±2 With Immediate Mask
{ "ANLD", 0x9C, 0xfc, 1, fmnop2, fopPx, fopA}, // ANLD Pp,A Logical AND Port 4±7 With Accumulator Mask
{ "CALL", 0x14, 0x1f, 2, fmnop1, fopJMP},
{ "CLR A", 0x27, 0xff, 1, 0}, // CLR A
{ "CLR C", 0x97, 0xff, 1, 0}, // CLR C Clear Carry Bit
{ "CLR F1", 0xA5, 0xff, 1, 0}, // CLR F1 Clear Flag 1
{ "CLR F0", 0x85, 0xff, 1, 0}, // CLR F0 Clear Flag 0
{ "CPL A", 0x37, 0xff, 1, 0}, // CPL A Complement Accumulator
{ "CPL C", 0xA7, 0xff, 1, 0}, // CPL C Complement Carry Bit
{ "CPL F0", 0x95, 0xff, 1, 0}, // CPL F0 COMPLEMENT FLAG 0
{ "CPL F1", 0xB5, 0xff, 1, 0}, // CPL F1 COMPLEMENT FLAG 1
{ "DA A", 0x57, 0xff, 1, 0}, // DA A Decimal Adjust Accumulator
{ "DEC A", 0x07, 0xff, 1, 0}, // DEC A Decrement Accumulator
{ "DEC", 0xC8, 0xf8, 1, fmnop1, fopRx}, // DEC Rr Decrement Register
{ "DIS I", 0x15, 0xff, 1, 0}, // DIS I Disable IBF Interrupt
{ "DIS TCNTI", 0x35, 0xff, 1, 0}, // DIS TCNTI Disable Timer/Counter Interrupt
{ "DJNZ", 0xE8, 0xf8, 2, fmnop2, fopRx, fopJ}, // DJNZ Rr, address Decrement Register and Test
{ "EN DMA", 0xE5, 0xff, 1, 0}, // EN DMA Enable DMA Handshake Lines
{ "EN FLAGS", 0xF5, 0xff, 1, 0 }, // EN FLAGS Enable Master Interrupts
{ "EN I", 0x05, 0xff, 1, 0 }, // EN I Enable IBF Interrupt
{ "EN TCNTI", 0x25, 0xff, 1, 0}, // EN TCNTI Enable Timer/Counter Interrupt
{ "IN A,DBB", 0x22, 0xff, 1, 0}, // IN A,DBB Input Data Bus Buffer Contents to Accumulator
{ "IN", 0x08, 0xfc, 1, fmnop2, fopA, fopPx}, // IN A,Pp Input Port 1±2 Data to Accumulator
{ "INC A", 0x17, 0xff, 1, 0}, // INC A
{ "INC", 0x18, 0xf8, 1, fmnop1, fopRx}, // INC Rr Increment Register
{ "INC", 0x10, 0xfe, 1, fmnop1, fopRRx}, // INC @Rr Increment Data Memory Location
{ "JB", 0x12, 0x1f, 2, fopJB}, // JBb address Jump If Accumulator Bit is Set
{ "JC", 0xF6, 0xff, 2, fmnop1, fopJ }, //
{ "JF0", 0xB6, 0xff, 2, fmnop1, fopJ }, //
{ "JF1", 0x76, 0xff, 2, fmnop1, fopJ }, //
{ "JMP", 0x04, 0x1f, 2, fmnop1, fopJMP},
{ "JMPP @A", 0xB3, 0xff, 1, 0 }, // JMPP @A Indirect Jump Within Page
{ "JNC", 0xE6, 0xff, 2, fmnop1, fopJ }, //
{ "JNIBF", 0xD6, 0xff, 2, fmnop1, fopJ }, //
{ "JNT0", 0x26, 0xff, 2, fmnop1, fopJ }, // JNTO address Jump if TEST 0 is Low
{ "JNT1", 0x46, 0xff, 2, fmnop1, fopJ }, //
{ "JNZ", 0x96, 0xff, 2, fmnop1, fopJ }, //
{ "JOBF", 0x86, 0xff, 2, fmnop1, fopJ }, //
{ "JTF", 0x16, 0xff, 2, fmnop1, fopJ }, //
{ "JT0", 0x36, 0xff, 2, fmnop1, fopJ }, //
{ "JT1", 0x56, 0xff, 2, fmnop1, fopJ }, //
{ "JZ", 0xC6, 0xff, 2, fmnop1, fopJ }, //
{ "MOV", 0x23, 0xff, 2, fmnop2, fopA, fopIMM }, // MOV A,Ýdata Move Immediate Data to Accumulator
{ "MOV A,PSW", 0xC7, 0xff, 1, 0}, // MOV A,PSW Move PSW Contents to Accumulator
{ "MOV", 0xF8, 0xf8, 1, fmnop2, fopA, fopRx }, // MOV A,Rr Move Register Contents to Accumulator
{ "MOV", 0xF0, 0xfe, 1, fmnop2, fopA, fopRRx }, // MOV A,@Rr Move Data Memory Contents to Accumulator
{ "MOV A,T", 0x42, 0xff, 1, 0}, // MOV A,T Move Timer/Counter Contents to Accumulator
{ "MOV PSW,A", 0xD7, 0xff, 1, 0}, // MOV PSW,A Move Accumulator Contents to PSW
{ "MOV", 0xA8, 0xf8, 1, fmnop2, fopRx, fopA }, // MOV Rr,A Move Accumulator Contents to Register
{ "MOV", 0xB8, 0xf8, 2, fmnop2, fopRx, fopIMM }, // MOV Rr,Ýdata Move Immediate Data to Register
{ "MOV", 0xA0, 0xfe, 1, fmnop2, fopRRx, fopA }, // MOV @Rr,A Move Accumulator Contents to Data Memory
{ "MOV", 0xB0, 0xfe, 2, fmnop2, fopRRx, fopIMM }, // MOV @Rr,Ýdata Move Immediate Data to Data Memory
{ "MOV STS,A", 0x90, 0xff, 1, 0}, // MOV STS,A Move Accumulator Contents to STS Register
{ "MOV T,A", 0x62, 0xff, 1, 0}, // MOV T,A Move Accumulator Contents to Timer/Counter
{ "MOVD", 0x0C, 0xfc, 2, fmnop2, fopA, fopPx }, // MOVD A,Pp Move Port 4±7 Data to Accumulator
{ "MOVD", 0x3C, 0xfc, 2, fmnop2, fopPx, fopA }, // MOVD Pp,A Move Accumulator Data to Port 4, 5, 6 and 7
{ "MOVP A,@A", 0xA3, 0xff, 1, 0}, // MOVP A,@A Move Current Page Data to Accumulator
{ "MOVP3 A,@A", 0xE3, 0xff, 1, 0}, // MOVP3 A,@A Move Page 3 Data to Accumulator
{ "NOP", 0x00, 0xff, 1, 0},
{ "ORL", 0x48, 0xf8, 1, fmnop2, fopA, fopRx}, // ORL A,Rr Logical OR Accumulator With Register Mask
{ "ORL", 0x40, 0xfe, 1, fmnop2, fopA, fopRRx}, // ORL A,@Rr Logical OR Accumulator With Memory Mask
{ "ORL", 0x43, 0xff, 2, fmnop2, fopA, fopIMM}, // ORL A,ÝData Logical OR Accumulator With Immediate Mask
{ "ORL", 0x88, 0xfc, 2, fmnop2, fopPx, fopIMM}, // ORL Pp,Ýdata Logical OR Port 1±2 With Immediate Mask
{ "ORLD", 0x8C, 0xfc, 2, fmnop2, fopPx, fopA}, // ORLD Pp,A Logical OR Port 4±7 With Accumulator Mask
{ "OUT DBB,A", 0x02, 0xff, 1, 0}, // OUT DBB,A Output Accumulator Contents to Data Bus Buffer
{ "OUTL", 0x38, 0xfc, 1, fmnop2, fopPx, fopA }, // OUTL Pp,A Output Accumulator Data to Port 1 and 2
{ "RET", 0x83, 0xff, 1, 0}, // RET Return Without PSW Restore
{ "RETR", 0x93, 0xff, 1, 0}, // RET Return Without PSW Restore
{ "RL A", 0xE7, 0xff, 1, 0}, // RL A Rotate Left Without Carry
{ "RLC A", 0xF7, 0xff, 1, 0}, // RLC A Rotate Left Through Carry
{ "RR A", 0x77, 0xff, 1, 0}, // RR A Rotate Right Without Carry
{ "RRC A", 0x67, 0xff, 1, 0}, // RRC A Rotate Right Through Carry
{ "SEL RB0", 0xC5, 0xff, 1, 0}, // SEL RB0 Select Register Bank 0
{ "SEL RB1", 0xD5, 0xff, 1, 0}, // SEL RB1 Select Register Bank 1
{ "STOP TCNT", 0x65, 0xff, 1, 0}, // STOP TCNT Stop Timer/Event Counter
{ "STRT CNT", 0x45, 0xff, 1, 0}, // STRT CNT Start Event Counter
{ "STRT T", 0x55, 0xff, 1, 0}, // STRT T Start Timer
{ "SWAP A", 0x47, 0xff, 1, 0}, // SWAP A Swap Nibbles Within Accumulator
{ "XCH", 0x28, 0xf8, 1, fmnop2, fopA, fopRx}, // XCH ARr Exchange Accumulator-Register Contents
{ "XCH", 0x20, 0xfe, 1, fmnop2, fopA, fopRRx}, // XCH A,@Rr Exchange Accumulator and Data Memory Contents
{ "XCHD", 0x30, 0xfe, 1, fmnop2, fopA, fopRRx}, // XCHD A,@Rr Exchange Accumulator and Data Memory 4-bit Data
{ "XRL", 0xD8, 0xf8, 1, fmnop2, fopA, fopRx}, // XRL A,Rr Logical XOR Accumulator With Register Mask
{ "XRL", 0xD0, 0xfe, 1, fmnop2, fopA, fopRRx}, // XRL A,@Rr Logical XOR Accumulator With Memory Mask
{ "XRL", 0xD3, 0xff, 2, fmnop2, fopA, fopIMM}, // XRL A,Ýdata, Logical XOR Accumulator With Immediate Mask
{ "???", 0, 0, 1, 0} // All others (zero-mask will be true - if reached, len=1)
};
static int instr1(unsigned char *p)
{
struct instr *i= instrs;
for (; ; i++) {
if ((*p & i->opcdmsk) == i->opcd) {
printf("%04X: ", PC); // print Program Counter
PC+=i->len; // we increment PC as if CPU did for JMP instructions(?)
printf("%02X ", p[0]); // write 1 or 2 code bytes
if (i->len==2) printf("%02X ", p[1]);
else printf(" ");
printf("%s", i->mn); // write mnemonic
if (i->fmnop) i->fmnop(p, i->fop1, i->fop2); // write 0, 1 or 2 operands
printf("\n");
return i->len;
}
}
}
/* Extern.
Disassemble iNTEL UPI-41/42 machine code
of n bytes, from p + offset
*/
void dasm42(char *p, int offs, int n)
{
p+=offs;
PC=offs;
n+=offs;
for (; PC < n;) p+=instr1(p);
}
/********** NOTES ****************************************************
Addressing:
- implicite (in instr)
- register Rn (0..7)
- indexed @Rn (0..1)
- A
- # (0..$ff)
- addr, 1 byte + PC (0..$ffff)
--------------------
RAM (DATA) 256 bytes
--------------------
0..7 R0..R7 BANK0 (Bs in PSW)
8..23 STACK (8x16bit) .....
24..31 R0..R7 BANK1
...... to top: "RAM" .....
R0, R1 can be index register
----------------
ROM (PROGRAM) 2K
----------------
RESET: $0000
IBR INT: $0003
TIMER INT: $0007
-----------
PC - 10-bit (not 11?)
-----------
PC always points to next instruction.
----
JUMP
----
a.) absolute address: JMP $35E = aa a9 a8 0 0 1 0 0 a7 a6 a5 a4 a3 a2 a1 a0 (2-byte instr)
b.) "relative" (op -> PC-LO): JZ $addr = $C6 $op (2-byte instr)
// OK.. "If a conditional JUMP or indirect JUMP begins in location 255 of a page, it must reference a destination on the following page"
--------
PC-stack
--------
8x16 bits: call/int saves PSW[7..4]&PC[11..0]
-------------------------
PSW - program status word
-------------------------
7 6 5 4 | 3 | 2 1 0
C AC F0 Bs| - | SP
CALL: push PC&PSW[7..4]
RET: pop PC
RETR: pop PC&PSW[7..4]
On-chip oscillator
------------------
1 to 12.5 MHz
or external
-------------------
8-bit Timer/Counter
-------------------
Timer-mode
- increments on OSC + 32-prescale
- START T .. STOP TCNT
Counter-mode
- increments on falling edges on TEST1-pin
- START CNT .. STOP TCNT
- MOV T,A and MOV A,T for reading/writing
Timer/Counter OVERFLOW
----------------------
fe..ff..00
1. sets timer flag (TF) - then can be tested by JTF (which clears TF)
2. generates IRQ
3. EN/DIS TCNTI
4. if enabled: CALL $0007 happens
----------
INTERRUPTS
----------
IBF:
- higher pri
- EN/DIS I
- CS & RW triggers
Timer
- EN/DIS TCNTI
-
1. IRQ set + disable all interrupts
2. CALL 3 (IBF) or 7 (T)
3. entering ISR clears IRQ
4. ISR
5. RETR (re-enables interrupt)
HOST INTERRUPTS
---------------
EN FLAGS will allocate P24/P25 to OBF/_IBF (only RESET clears it)
"These interrupt outputs reflect the internal status of the OBF flag and the IBF inverted flag."
"Note, these outputs may be inhibited by writing a '0' to these pins. Reenabling interrupts is done by writing a '1' to these port pins."
==> so host cpu doesn't have to poll the same bits in STATUS REG (0x64); it can have it as interrupts (this is set in the code after RESET..)
------------
HOST CPU I/O
------------
!!! There are 3 registers in the UPI on the host side !!! (NB. host CPU writes into DBBIN..)
<--R-- STATUS <--- MOV STS,A + JF0,JF1,JOBF,JNIBF
HOST CPU I/O <--R-- DBBOUT <--- OUT DBB,A
--W--> DBBIN ---> IN A,DBB
RD WR A0
0 1 0 (0x60) Read DBBOUT register
0 1 1 (0x64) Read STATUS register
1 0 0 (0x60) Write DBBIN!
1 0 1 (0x64) Write DBBIN!
==> A0-pin simply latches into STATUS-F1-bit on host write, what the UPI can test by JF1 $xx.
-----------------
Data buffers: DBB
-----------------
DBBIN, DBBOUT
"When CS, A0 and RD are low, the contents of the DBBOUT register is placed on the three-state Data lines D0-D7 and the OBF flag is cleared."
"When CS and WR are low, the contents of the system data bus is latched into DBBIN. Also, the IBF flag is set and an interrupt is generated, if enabled."
--------------------
ST - status register
--------------------
= Bus buffer register status word.
ST7 ST6 ST5 ST4 | F1 F0 | IBF OBF
ST7-4: user defined, MOV STS,A writes them, UPI doesn't care more about it.
F0: user defined (JF0 $xx)
F1 = A0-pin (Command/Data)
"OBF Output Buffer Full: This flag is automatically set when the UPI-Microcomputer loads the DBBOUT register and is cleared when the master processor reads the data register."
"IBF Input Buffer Full: This flag is set when the master processor writes a character to the DBBIN register and is cleared when the UPI INputs the data register contents to its accumulator."
---------
I/O PORTS
---------
2 x 8-bit: P1 and P2
OUTL Pn,A
IN A,Pn
"To use a particular PORT pin as an input, a logic '1' must first be written to that pin."
*/