#include "compiler.h"
#include "cpucore.h"
#include "pccore.h"
#include "iocore.h"
#include "bios.h"
#include "biosmem.h"
#include "rsbios.h"
static const UINT rs_speed[] = {
// 5MHz
0x0800, 0x0400, 0x0200, 0x0100,
0x0080, 0x0040, 0x0020, 0x0010,
0x0008, 0x0004, 0x0002, 0x0001,
// 4MHz
0x0680, 0x0340, 0x01a0, 0x00d0,
0x0068, 0x0034, 0x001a, 0x000d};
void bios0x19(void) {
UINT8 speed;
UINT8 mode;
RSBIOS rsb;
UINT16 doff;
UINT16 cnt;
UINT16 dseg;
UINT8 flag;
if (CPU_AH < 2) {
// 通信速度…
mode = CPU_CH | 0x02;
speed = CPU_AL;
if (speed >= 8) {
speed = 4; // 1200bps
}
if (mem[MEMB_BIOS_FLAG1] & 0x80) { // 4MHz?
speed += 12;
}
#if 1 // NP2では未サポートの為 強行(汗
mode &= ~1;
#else
if (mode & 1) {
if (speed < (12 + 6)) {
speed += 2;
}
else {
mode &= ~1;
}
}
// シリアルリセット
iocore_out8(0x32, 0x00); // dummy instruction
iocore_out8(0x32, 0x00); // dummy instruction
iocore_out8(0x32, 0x00); // dummy instruction
iocore_out8(0x32, 0x40); // reset
iocore_out8(0x32, mode); // mode
iocore_out8(0x32, CPU_CL); // cmd
#endif
iocore_out8(0x77, 0xb6);
iocore_out8(0x75, (UINT8)rs_speed[speed]);
iocore_out8(0x75, (UINT8)(rs_speed[speed] >> 8));
ZeroMemory(&rsb, sizeof(rsb));
rsb.FLAG = (CPU_AH << 4);
rsb.CMD = CPU_CL;
sysport.c &= ~7;
if (!(CPU_CL & RCMD_IR)) {
rsb.FLAG |= RFLAG_INIT;
if (CPU_CL & RCMD_RXE) {
sysport.c |= 1;
pic.pi[0].imr &= ~PIC_RS232C;
}
}
rsb.STIME = CPU_BH;
if (!rsb.STIME) {
rsb.STIME = 0x04;
}
rsb.RTIME = CPU_BL;
if (!rsb.RTIME) {
rsb.RTIME = 0x40;
}
doff = CPU_DI + sizeof(RSBIOS);
STOREINTELWORD(rsb.HEADP, doff);
STOREINTELWORD(rsb.PUTP, doff);
STOREINTELWORD(rsb.GETP, doff);
doff += CPU_DX;
STOREINTELWORD(rsb.TAILP, doff);
cnt = CPU_DX >> 3;
STOREINTELWORD(rsb.XOFF, cnt);
cnt += CPU_DX >> 2;
STOREINTELWORD(rsb.XON, cnt);
// ポインタ〜
SETBIOSMEM16(MEMW_RS_CH0_OFST, CPU_DI);
SETBIOSMEM16(MEMW_RS_CH0_SEG, CPU_ES);
MEMR_WRITES(CPU_ES, CPU_DI, &rsb, sizeof(rsb));
CPU_AH = 0;
}
else if (CPU_AH < 7) {
doff = GETBIOSMEM16(MEMW_RS_CH0_OFST);
dseg = GETBIOSMEM16(MEMW_RS_CH0_SEG);
if ((!doff) && (!dseg)) {
CPU_AH = 1;
return;
}
flag = MEMR_READ8(dseg, doff + R_FLAG);
if (!(flag & RFLAG_INIT)) {
CPU_AH = 1;
return;
}
switch(CPU_AH) {
case 0x02:
CPU_CX = MEMR_READ16(dseg, doff + R_CNT);
break;
case 0x03:
iocore_out8(0x30, CPU_AL);
break;
case 0x04:
cnt = MEMR_READ16(dseg, doff + R_CNT);
if (cnt) {
UINT16 pos;
// データ引き取り
pos = MEMR_READ16(dseg, doff + R_GETP);
CPU_CX = MEMR_READ16(dseg, pos);
// 次のポインタをストア
pos += 2;
if (pos >= MEMR_READ16(dseg, doff + R_TAILP)) {
pos = MEMR_READ16(dseg, doff + R_HEADP);
}
MEMR_WRITE16(dseg, doff + R_GETP, pos);
// カウンタをデクリメント
cnt--;
MEMR_WRITE16(dseg, doff + R_CNT, cnt);
// XONを送信?
if ((flag & RFLAG_XOFF) &&
(cnt < MEMR_READ16(dseg, doff + R_XOFF))) {
iocore_out8(0x30, RSCODE_XON);
flag &= ~RFLAG_XOFF;
}
flag &= ~RFLAG_BOVF;
CPU_AH = 0;
MEMR_WRITE8(dseg, doff + R_FLAG, flag);
return;
}
else {
CPU_AH = 3;
}
break;
case 0x05:
iocore_out8(0x32, CPU_AL);
if (CPU_AL & RCMD_IR) {
flag &= ~RFLAG_INIT;
MEMR_WRITE8(dseg, doff + R_FLAG, flag);
sysport.c &= ~1;
pic.pi[0].imr |= PIC_RS232C;
}
else if (!(CPU_AL & RCMD_RXE)) {
sysport.c &= ~1;
pic.pi[0].imr |= PIC_RS232C;
}
else {
sysport.c |= 1;
pic.pi[0].imr &= ~PIC_RS232C;
}
MEMR_WRITE8(dseg, doff + R_CMD, CPU_AL);
break;
case 0x06:
CPU_CH = iocore_inp8(0x32);
CPU_CL = iocore_inp8(0x33);
break;
}
CPU_AH = 0;
if (flag & RFLAG_BOVF) {
MEMR_WRITE8(dseg, doff + R_FLAG, (UINT8)(flag & (~RFLAG_BOVF)));
CPU_AH = 2;
}
}
else {
CPU_AH = 0;
}
}
RetroPC.NET-CVS <cvs@retropc.net>