/* di8274.c
interrupt driver for 8274
Stewart, November 8, 1982 2:56 PM
November 8, 1982 5:09 PM osstatics, add nbPutChar()
February 23, 1983 10:32 AM remove wdc
February 23, 1983 12:53 PM remove osstatics
February 23, 1983 2:56 PM new EnableInt, FlushInput,
CallSwat -> CallDebug, flush Set8274
February 26, 1983 3:33 PM EOI fixes
*/
#include "ec.h"
#include "Lark.h"
#include "env.h"
#include "RingBuffer.h"
/* context */
extern Block();
/* interrupts */
extern EnableInt();
/* runtime */
extern CallDebugger();
/* ringbuffer */
extern InitRingBuffer();
extern WriteRingBuffer();
extern RingBufferEmpty();
extern ReadRingBuffer();
/* machine code */
extern OutByte();
extern InByte();
extern /* FORWARD */ mySIOInt();
static struct CBuf rb[2];
static struct CBuf tb[2];
static int busy[2];
Init8274()
{
FlushInput(0);
FlushInput(1);
InitRingBuffer(&tb[0], tb[0].abuf, CBS-2);
InitRingBuffer(&tb[1], tb[1].abuf, CBS-2);
busy[0] = busy[1] = false;
Baud(1200, 0);
Baud(1200, 1);
EnableInt(&mySIOInt, SIOTyp);
};
FlushInput(ch)
int ch;
{
if (ch) InitRingBuffer(&rb[1], rb[1].abuf, CBS-2);
else InitRingBuffer(&rb[0], rb[0].abuf, CBS-2);
};
nbPutChar(c)
char c;
{
struct CBuf *p;
p = &tb[0];
while (!WriteRingBuffer(p, c));
if (!busy[0] && !RingBufferEmpty(p)) {
busy[0] = 1;
SIOPutC(0, ReadRingBuffer(p));
};
};
PutChar(c)
char c;
{
PutC(0, c);
};
PutCRChar(c)
char c;
{
PutChar(c);
if (c=='\r') PutChar('\n');
};
PutC(ch, c)
int ch;
char c;
{
struct CBuf *p;
p = &tb[ch];
while (!WriteRingBuffer(p, c)) Block();
if (!busy[ch] && !RingBufferEmpty(p)) {
busy[ch] = 1;
SIOPutC(ch, ReadRingBuffer(p));
};
};
int GetChar()
{
return(GetC(0));
};
int GetC(ch)
int ch;
{
struct CBuf *p;
p = &rb[ch];
while (RingBufferEmpty(p)) Block();
return(ReadRingBuffer(p) & 0177);
};
int Chav()
{
return(AvC(0));
};
int AvC(ch)
int ch;
{
return(!RingBufferEmpty(&rb[ch]));
};
Baud(mbr, ch)
int mbr, ch;
{
int dr, load, hold;
if (ch == 0) { /* use 9513 channel 0 (FOUT) */
if (mbr == 300) { MM(0x0ac0); WR4(ch, 0x008c); };
else WR4(ch, 0x4c);
if (mbr==600) MM(0x0ac0);
if (mbr==1200) MM(0x088c0);
if (mbr==2400) MM(0x084c0);
if (mbr==4800) MM(0x082c0);
if (mbr==9600) MM(0x08a00);
if (mbr==19200) MM(0x08500);
};
if (ch==1) { /* use 9513 channel 4 */
WR4(ch, 0x4c); /* always use /16 mode */
mbr = mbr/100;
dr = 960/mbr; /* 960 = 15360/16 (16 for 8274 division ratio) */
hold = dr/2;
load = dr-hold;
OutByte(TimCtl, 0xc8); /* disarm ch 4 */
OutByte(TimCtl, 0x04); /* set data pointer for ch 4 */
OutWord(TimData, 0x1b62); /* Mode J, src F1, toggle, count up, binary */
OutWord(TimData, load);
OutWord(TimData, hold);
OutByte(TimCtl, 0x48); /* load ch 4 */
OutByte(TimCtl, 0x28); /* arm ch 4 */
};
};
static int iretCode;
static mySIOInt()
{
int type;
/* read RR2 of ch. B to get modified vector */
type = RR2(1) & 07;
switch (type) {
case 0: txe(1); break;
case 1: CallD(ecInt+2); break;
case 2: rxa(1); break;
case 3: sprx(1); break;
case 4: txe(0); break;
case 5: CallD(ecInt+3); break;
case 6: rxa(0); break;
case 7: sprx(0); break;
default: CallD(ecInt+1);
};
if (iretCode) WR0(0, 0x38); /* eoi */
return(iretCode);
};
CallD(n)
int n;
{
WR0(0, 0x38); /* eoi */
DoEOI();
iretCode = false;
CallDebugger(n);
};
static rxa(ch)
int ch;
{
char c;
iretCode = true;
c = SIOGetC(ch);
if (c == 0) CallD(0);
else WriteRingBuffer(&rb[ch], c);
};
static txe(ch)
int ch;
{
struct CBuf *p;
iretCode = true;
p = &tb[ch];
if (RingBufferEmpty(p)) {
WR0(ch, 0x28);
busy[ch] = 0;
};
else SIOPutC(ch, ReadRingBuffer(p));
};
static sprx(ch)
int ch;
{
iretCode = true;
WR0(ch, 0xf0); /* forget it */
};
static WR0(ch, rv)
int ch, rv;
{
ch = SIOCmdP(ch);
OutByte(ch, rv&0xff);
};
static int RR2(ch)
int ch;
{
ch = SIOCmdP(ch);
OutByte(ch, 2);
return(InByte(ch) & 0xff);
};
static SIOGetC(ch)
int ch;
{
ch = SIODataP(ch);
return(InByte(ch)&0177);
};
static SIOPutC(ch, v)
int ch;
char v;
{
ch = SIODataP(ch);
OutByte(ch, v);
};
static SIOCmdP(ch)
int ch;
{
if (ch==0) ch = sioctla;
else ch = sioctlb;
return(ch);
};
static SIODataP(ch)
int ch;
{
if (ch==0) ch = siodata;
else ch = siodatb;
return(ch);
};
static MM(rv)
int rv;
{
OutByte(TimCtl, 0x17);
OutWord(TimData, rv);
};
static WR4(ch, rv)
int ch, rv;
{
ch = SIOCmdP(ch);
OutByte(ch, 0x04);
OutByte(ch, rv&0xff);
};
static OutWord(port, val)
int port, val;
{
OutByte(port, val&0xff);
OutByte(port, (val >> 8)&0xff);
};