@@ 10,11 10,11 @@
#include "../port/netif.h"
/*
- * Stargate's Avanstar serial board. There are ISA, EISA, microchannel versions.
- * At the moment we only handle the ISA one.
+ * Stargate's Avanstar serial board. There are ISA, EISA, microchannel
+ * versions. We only handle the ISA one.
*/
typedef struct Astar Astar;
-typedef struct Astarport Astarchan;
+typedef struct Astarchan Astarchan;
enum
{
@@ 24,17 24,28 @@ enum
ISAid1= 0x13,
ISActl1= 1, /* board control */
ISAien= 1<<7, /* interrupt enable */
- ISAirqm= 4, /* shift for 3 bit irq code */
+ ISAirq= 7<<4, /* mask for irq code */
ISAdl= 1<<1, /* download bit (1 == download) */
ISApr= 1<<0, /* program ready */
ISActl2= 2, /* board control */
ISA186ien= 1<<7, /* I186 irq enable bit state */
ISA186idata= 1<<6, /* I186 irq data bit state */
- ISAmemen= 1<<4, /* enable memory to respond to ISA cycles */
- ISAmembank= 0, /* shift for 4 bit memory bank */
- ISAmemaddr= 3, /* bits 14-19 of the boards mem address */
+ ISAmen= 1<<4, /* enable memory to respond to ISA cycles */
+ ISAmbank= 0, /* shift for 4 bit memory bank */
+ ISAmaddr= 3, /* bits 14-19 of the boards mem address */
ISAstat1= 4, /* board status (1 bit per channel) */
ISAstat2= 5, /* board status (1 bit per channel) */
+
+ Maxcards= 3,
+};
+
+/* IRQ codes */
+static int isairqcode[16] =
+{
+ -1, -1, -1, 0<<4,
+ 1<<4, 2<<4, -1, -1,
+ -1, 3<<4, 4<<4, 5<<4,
+ 6<<4, -1, -1, 7<<4,
};
/* control program global control block */
@@ 59,18 70,50 @@ struct GCB
ushort cmdserv; /* channel command service request 'X' */
};
+enum
+{
+ /* GCB.cmd commands/codes */
+ Greadycmd= 0,
+ Gdiagcmd= 1,
+ Gresetcmd= 2,
+
+ /* GCB.status values */
+ Gready= 0,
+ Gstopped= 1,
+ Gramerr= 2,
+ Gbadcmd= 3,
+ Gbusy= 4,
+
+ /* GCB.type values */
+ Gx00m= 0x6,
+ G100e= 0xA,
+ Gx00i= 0xC,
+
+ /* GCB.status2 bits */
+ Ghas232= (1<<0),
+ Ghas422= (1<<1),
+ Ghasmodems= (1<<2),
+ Ghasrj11s= (1<<7),
+ Ghasring= (1<<8),
+ Ghasdcd= (1<<9),
+ Ghasdtr= (1<<10),
+ Ghasdsr= (1<<11),
+ Ghascts= (1<<12),
+ Ghasrts= (1<<13),
+};
+
/* control program channel control block */
typedef struct CCB CCB;
struct CCB
{
ushort baud; /* baud rate */
ushort format; /* data format */
- ushort line; /* line protocol */
+ ushort proto; /* line protocol */
ushort insize; /* input buffer size */
ushort outsize; /* output buffer size */
ushort intrigger; /* input buffer trigger rate */
ushort outlow; /* output buffer low water mark */
- ushort xon; /* xon characters */
+ char xon[2]; /* xon characters */
ushort inhigh; /* input buffer high water mark */
ushort inlow; /* input buffer low water mark */
ushort cmd; /* channel command */
@@ 89,15 132,90 @@ struct CCB
ushort mstat; /* modem status */
ushort bstat; /* blocking status */
ushort rflag; /* character received flag */
- ushort xoff; /* xoff characters */
+ char xoff[2]; /* xoff characters */
ushort status2;
- uchort strip; /* strip/error characters */
+ char strip[2]; /* strip/error characters */
+};
+
+enum
+{
+ /* special baud rate codes for CCB.baud */
+ Cb76800= 0xff00,
+ Cb115200= 0xff01,
+
+ /* CCB.format fields */
+ C5bit= 0<<0, /* data bits */
+ C6bit= 0<<1,
+ C7bit= 0<<2,
+ C8bit= 0<<3,
+ C1stop= 0<<2, /* stop bits */
+ C2stop= 1<<2,
+ Cnopar= 0<<3, /* parity */
+ Coddpar= 1<<3,
+ Cevenpar= 3<<3,
+ Cmarkpar= 5<<3,
+ Cspacepar= 7<<3,
+ Cnormal= 0<<6, /* normal mode */
+ Cecho= 1<<6, /* echo mode */
+ Clloop= 2<<6, /* local loopback */
+ Crloop= 3<<6, /* remote loopback */
+
+ /* CCB.proto fields */
+ Cobeyxon= 1<<0, /* obey received xoff/xon controls */
+ Canyxon= 1<<1, /* any rcvd character restarts xmit */
+ Cgenxon= 1<<2, /* generate xoff/xon controls */
+ Cobeycts= 1<<3, /* obey hardware flow ctl */
+ Cgendtr= 1<<4, /* dtr off when uart rcvr full */
+ C½duplex= 1<<5, /* rts off while xmitting */
+ Cgenrts= 1<<6, /* generate hardware flow ctl */
+ Cmctl= 1<<7, /* direct modem control via CCB.mctl */
+ Cstrip= 1<<12, /* to strip out characters */
+ Ceia422= 1<<13, /* to select eia 422 lines */
+
+ /* CCB.cmd fields */
+ Cconfall= 1<<0, /* configure channel and UART */
+ Cconfchan= 1<<1, /* configure just channel */
+ Cflushin= 1<<2, /* flush input buffer */
+ Cflushout= 1<<3, /* flush output buffer */
+ Crcvena= 1<<4, /* enable receiver */
+ Crcvdis= 1<<5, /* disable receiver */
+ Cxmtena= 1<<6, /* enable transmitter */
+ Cxmtdis= 1<<7, /* disable transmitter */
+ Cmreset= 1<<9, /* reset modem */
+
+ /* CCB.errstat fields */
+ Coverrun= 1<<0,
+ Cparity= 1<<1,
+ Cframing= 1<<2,
+ Cbreak= 1<<3,
+
+ /* CCB.mctl fields */
+ Cdtrctl= 1<<0,
+ Crtsctl= 1<<1,
+ Cbreakctl= 1<<4
+
+
+ /* CCB.mstat fields */
+ Cctsstat= 1<<0,
+ Cdsrstat= 1<<1,
+ Cristat= 1<<2,
+ Cdcdstat= 1<<3,
+
+ /* CCB.bstat fields */
+ Cbrcvoff= 1<<0,
+ Cbxmtoff= 1<<1,
+ Clbxoff= 1<<2, /* transmitter blocked by XOFF */
+ Clbcts= 1<<3, /* transmitter blocked by CTS */
+ Crbxoff= 1<<4, /* remote blocked by xoff */
+ Crbrts= 1<<4, /* remote blocked by rts */
};
/* host per controller info */
struct Astar
{
- int port; /* number of first port */
+ ISAConf;
+ int id; /* from plan9.ini */
+ int ramsize; /* 16k or 256k */
GCB *gbc; /* board comm area */
Astarchan *c; /* channels */
};
@@ 107,8 225,10 @@ struct Astarchan
{
QLock;
+ CCB *ccb; /* control block */
+
/* buffers */
- int (*putc)(Queue*, int);
+
Queue *iq;
Queue *oq;
@@ 123,23 243,44 @@ struct Astarchan
uchar *oe;
};
-/*
- * Stargate's Avanstar serial port cards. Currently only the ISA version
- * is supported.
- */
+Astar *a[Maxcard];
+
+int astarsetup(Astar*);
+
void
-avanstarreset(void)
+astarreset(void)
{
int i;
+ Astar *a;
Dirtab *dp;
for(i = 0; i < Maxcard; i++){
- sc = scard[i] = xalloc(sizeof(Scard));
- if(isaconfig("serial", i, sc) == 0){
- xfree(sc);
+ a = astar[i] = xalloc(sizeof(Astar));
+ if(isaconfig("serial", i, &a) == 0){
+ xfree(a);
+ astar[i] = 0;
break;
}
+ if(strcmp(a->type, "a100i") == 0 || strcmp(a->type,"A100I") == 0)
+ a->ramsize = 16*1024;
+ else if(strcmp(a->type, "a200i") == 0 || strcmp(a->type,"A200I") == 0)
+ a->ramsize = 256*1024;
+ else
+ continue;
+ if(a->mem == 0)
+ a->mem = 0xD0000;
+ if(a->irq == 0)
+ a->irq = 15;
+ a->id = i;
+
+ if(astarsetup(a) < 0){
+ xfree(a);
+ astar[i] = 0;
+ continue;
+ }
+ }
+
ndir = 3*nuart;
ns16552dir = xalloc(ndir * sizeof(Dirtab));
dp = ns16552dir;
@@ 159,3 300,61 @@ avanstarreset(void)
dp++;
}
}
+
+void
+astarinit(void)
+{
+}
+
+int isaport[] =
+ { 0x200, 0x208, 0x300, 0x308, 0x600, 0x608, 0x700, 0x708, 0 };
+
+int
+isax00i(int port)
+{
+ uchar c, c1;
+
+ if(port < 0)
+ return 0;
+
+ c = inb(port + ISAid);
+ c1 = inb(port + ISAid);
+ return (c == ISAid0 && c1 == ISAid1)
+ || (c == ISAid1 && c1 == ISAid0));
+}
+
+int
+astarsetup(Astar *a)
+{
+ int i, j, found;
+
+ /* see if the card exists */
+ found = 0;
+ if(a->port == 0)
+ for(i = 0; isaport[i]; i++){
+ a->port = isaport[i];
+ found = isax00i(isaport[i]);
+ if(found){
+ isaport[i] = -1;
+ break;
+ }
+ }
+ else
+ found = isax00i(a->port);
+ if(!found){
+ print("avanstar %d not found\n", a->id);
+ return -1;
+ }
+
+ /* set memory address */
+ outb(a->port + ISAmaddr, (a->mem>>12) & 0xfc);
+ a->gcb = KZERO | a->mem;
+
+ /* set interrupt level */
+ if(isairqcode(a->irq) == -1){
+ print("Avanstar %d bad irq %d\n", a->id, a->irq);
+ return -1;
+ }
+ c = inb(a->port + ISActl1) & ~ISAirq;
+ outb(a->port + ISActl1, c | isairqcode(a->irq));
+}