1*74a4d8c2SCharles.Forsyth #include "u.h"
2*74a4d8c2SCharles.Forsyth #include "lib.h"
3*74a4d8c2SCharles.Forsyth #include "mem.h"
4*74a4d8c2SCharles.Forsyth #include "dat.h"
5*74a4d8c2SCharles.Forsyth #include "fns.h"
6*74a4d8c2SCharles.Forsyth #include "io.h"
7*74a4d8c2SCharles.Forsyth
8*74a4d8c2SCharles.Forsyth /*
9*74a4d8c2SCharles.Forsyth * SMC1 in UART mode
10*74a4d8c2SCharles.Forsyth */
11*74a4d8c2SCharles.Forsyth
12*74a4d8c2SCharles.Forsyth typedef struct Uartsmc Uartsmc;
13*74a4d8c2SCharles.Forsyth struct Uartsmc {
14*74a4d8c2SCharles.Forsyth IOCparam;
15*74a4d8c2SCharles.Forsyth ushort maxidl;
16*74a4d8c2SCharles.Forsyth ushort idlc;
17*74a4d8c2SCharles.Forsyth ushort brkln;
18*74a4d8c2SCharles.Forsyth ushort brkec;
19*74a4d8c2SCharles.Forsyth ushort brkcr;
20*74a4d8c2SCharles.Forsyth ushort rmask;
21*74a4d8c2SCharles.Forsyth };
22*74a4d8c2SCharles.Forsyth
23*74a4d8c2SCharles.Forsyth typedef struct Uart Uart;
24*74a4d8c2SCharles.Forsyth struct Uart
25*74a4d8c2SCharles.Forsyth {
26*74a4d8c2SCharles.Forsyth int port;
27*74a4d8c2SCharles.Forsyth int setup;
28*74a4d8c2SCharles.Forsyth uchar txbusy;
29*74a4d8c2SCharles.Forsyth
30*74a4d8c2SCharles.Forsyth Queue* iq;
31*74a4d8c2SCharles.Forsyth Queue* oq;
32*74a4d8c2SCharles.Forsyth void (*rx)(Queue*, int);
33*74a4d8c2SCharles.Forsyth void (*boot)(uchar*, int);
34*74a4d8c2SCharles.Forsyth
35*74a4d8c2SCharles.Forsyth ulong frame;
36*74a4d8c2SCharles.Forsyth ulong overrun;
37*74a4d8c2SCharles.Forsyth uchar rxbuf[128];
38*74a4d8c2SCharles.Forsyth char txbuf[16];
39*74a4d8c2SCharles.Forsyth BD* rxb;
40*74a4d8c2SCharles.Forsyth BD* txb;
41*74a4d8c2SCharles.Forsyth };
42*74a4d8c2SCharles.Forsyth
43*74a4d8c2SCharles.Forsyth Uart uart[1];
44*74a4d8c2SCharles.Forsyth int predawn = 1;
45*74a4d8c2SCharles.Forsyth
46*74a4d8c2SCharles.Forsyth static void uartintr(Ureg*, void*);
47*74a4d8c2SCharles.Forsyth static void uartkick(void*);
48*74a4d8c2SCharles.Forsyth
49*74a4d8c2SCharles.Forsyth static int
baudgen(int baud)50*74a4d8c2SCharles.Forsyth baudgen(int baud)
51*74a4d8c2SCharles.Forsyth {
52*74a4d8c2SCharles.Forsyth int d;
53*74a4d8c2SCharles.Forsyth
54*74a4d8c2SCharles.Forsyth d = ((m->cpuhz/baud)+8)>>4;
55*74a4d8c2SCharles.Forsyth if(d >= (1<<12))
56*74a4d8c2SCharles.Forsyth return ((d+15)>>3)|1;
57*74a4d8c2SCharles.Forsyth return d<<1;
58*74a4d8c2SCharles.Forsyth }
59*74a4d8c2SCharles.Forsyth
60*74a4d8c2SCharles.Forsyth static void
smcsetup(Uart * up,int baud)61*74a4d8c2SCharles.Forsyth smcsetup(Uart *up, int baud)
62*74a4d8c2SCharles.Forsyth {
63*74a4d8c2SCharles.Forsyth IMM *io;
64*74a4d8c2SCharles.Forsyth Uartsmc *p;
65*74a4d8c2SCharles.Forsyth BD *bd;
66*74a4d8c2SCharles.Forsyth SMC *smc;
67*74a4d8c2SCharles.Forsyth
68*74a4d8c2SCharles.Forsyth archenableuart(SMC1ID, 0);
69*74a4d8c2SCharles.Forsyth io = m->iomem;
70*74a4d8c2SCharles.Forsyth io->pbpar |= IBIT(24)|IBIT(25); /* enable SMC1 TX/RX */
71*74a4d8c2SCharles.Forsyth io->pbdir &= ~(IBIT(24)|IBIT(25));
72*74a4d8c2SCharles.Forsyth io->brgc1 = baudgen(baud) | BaudEnable;
73*74a4d8c2SCharles.Forsyth io->simode &= ~0xF000; /* SMC1 to NMSI mode, Tx/Rx clocks are BRG1 */
74*74a4d8c2SCharles.Forsyth
75*74a4d8c2SCharles.Forsyth bd = bdalloc(1);
76*74a4d8c2SCharles.Forsyth p = (Uartsmc*)KADDR(SMC1P);
77*74a4d8c2SCharles.Forsyth p->rbase = (ushort)bd;
78*74a4d8c2SCharles.Forsyth up->rxb = bd;
79*74a4d8c2SCharles.Forsyth bd->status = BDEmpty|BDWrap|BDInt;
80*74a4d8c2SCharles.Forsyth bd->length = 0;
81*74a4d8c2SCharles.Forsyth bd->addr = PADDR(up->rxbuf);
82*74a4d8c2SCharles.Forsyth bd = bdalloc(1);
83*74a4d8c2SCharles.Forsyth p->tbase = (ushort)bd;
84*74a4d8c2SCharles.Forsyth up->txb = bd;
85*74a4d8c2SCharles.Forsyth bd->status = BDWrap|BDInt;
86*74a4d8c2SCharles.Forsyth bd->length = 0;
87*74a4d8c2SCharles.Forsyth bd->addr = PADDR(up->txbuf);
88*74a4d8c2SCharles.Forsyth
89*74a4d8c2SCharles.Forsyth cpmop(InitRxTx, SMC1ID, 0);
90*74a4d8c2SCharles.Forsyth
91*74a4d8c2SCharles.Forsyth /* protocol parameters */
92*74a4d8c2SCharles.Forsyth p->rfcr = 0x18;
93*74a4d8c2SCharles.Forsyth p->tfcr = 0x18;
94*74a4d8c2SCharles.Forsyth p->mrblr = 1;
95*74a4d8c2SCharles.Forsyth p->maxidl = 1;
96*74a4d8c2SCharles.Forsyth p->brkln = 0;
97*74a4d8c2SCharles.Forsyth p->brkec = 0;
98*74a4d8c2SCharles.Forsyth p->brkcr = 1;
99*74a4d8c2SCharles.Forsyth smc = IOREGS(0xA80, SMC);
100*74a4d8c2SCharles.Forsyth smc->smce = 0xff; /* clear events */
101*74a4d8c2SCharles.Forsyth smc->smcm = 0x17; /* enable all possible interrupts */
102*74a4d8c2SCharles.Forsyth setvec(VectorCPIC+4, uartintr, up);
103*74a4d8c2SCharles.Forsyth smc->smcmr = 0x4820; /* 8-bit mode, no parity, 1 stop bit, UART mode, ... */
104*74a4d8c2SCharles.Forsyth smc->smcmr |= 3; /* enable rx/tx */
105*74a4d8c2SCharles.Forsyth }
106*74a4d8c2SCharles.Forsyth
107*74a4d8c2SCharles.Forsyth static void
uartintr(Ureg *,void * arg)108*74a4d8c2SCharles.Forsyth uartintr(Ureg*, void *arg)
109*74a4d8c2SCharles.Forsyth {
110*74a4d8c2SCharles.Forsyth Uart *up;
111*74a4d8c2SCharles.Forsyth int ch, i;
112*74a4d8c2SCharles.Forsyth BD *bd;
113*74a4d8c2SCharles.Forsyth SMC *smc;
114*74a4d8c2SCharles.Forsyth Block *b;
115*74a4d8c2SCharles.Forsyth
116*74a4d8c2SCharles.Forsyth up = arg;
117*74a4d8c2SCharles.Forsyth smc = IOREGS(0xA80, SMC);
118*74a4d8c2SCharles.Forsyth smc->smce = 0xff; /* clear all events */
119*74a4d8c2SCharles.Forsyth if((bd = up->rxb) != nil && (bd->status & BDEmpty) == 0){
120*74a4d8c2SCharles.Forsyth if(up->iq != nil && bd->length > 0){
121*74a4d8c2SCharles.Forsyth if(up->boot != nil){
122*74a4d8c2SCharles.Forsyth up->boot(up->rxbuf, bd->length);
123*74a4d8c2SCharles.Forsyth }else if(up->rx != nil){
124*74a4d8c2SCharles.Forsyth for(i=0; i<bd->length; i++){
125*74a4d8c2SCharles.Forsyth ch = up->rxbuf[i];
126*74a4d8c2SCharles.Forsyth up->rx(up->iq, ch);
127*74a4d8c2SCharles.Forsyth }
128*74a4d8c2SCharles.Forsyth }else{
129*74a4d8c2SCharles.Forsyth b = iallocb(bd->length);
130*74a4d8c2SCharles.Forsyth memmove(b->wp, up->rxbuf, bd->length);
131*74a4d8c2SCharles.Forsyth b->wp += bd->length;
132*74a4d8c2SCharles.Forsyth qbwrite(up->iq, b);
133*74a4d8c2SCharles.Forsyth }
134*74a4d8c2SCharles.Forsyth }
135*74a4d8c2SCharles.Forsyth bd->status |= BDEmpty|BDInt;
136*74a4d8c2SCharles.Forsyth } else if((bd = up->txb) != nil && (bd->status & BDReady) == 0){
137*74a4d8c2SCharles.Forsyth ch = -1;
138*74a4d8c2SCharles.Forsyth if(up->oq)
139*74a4d8c2SCharles.Forsyth ch = qbgetc(up->oq);
140*74a4d8c2SCharles.Forsyth if(ch != -1){
141*74a4d8c2SCharles.Forsyth up->txbuf[0] = ch;
142*74a4d8c2SCharles.Forsyth bd->length = 1;
143*74a4d8c2SCharles.Forsyth bd->status |= BDReady;
144*74a4d8c2SCharles.Forsyth }else
145*74a4d8c2SCharles.Forsyth up->txbusy = 0;
146*74a4d8c2SCharles.Forsyth }
147*74a4d8c2SCharles.Forsyth /* TO DO: modem status, errors, etc */
148*74a4d8c2SCharles.Forsyth }
149*74a4d8c2SCharles.Forsyth
150*74a4d8c2SCharles.Forsyth static void
uartkick(void * arg)151*74a4d8c2SCharles.Forsyth uartkick(void *arg)
152*74a4d8c2SCharles.Forsyth {
153*74a4d8c2SCharles.Forsyth Uart *up = arg;
154*74a4d8c2SCharles.Forsyth int s, c, i;
155*74a4d8c2SCharles.Forsyth
156*74a4d8c2SCharles.Forsyth s = splhi();
157*74a4d8c2SCharles.Forsyth while(up->txbusy == 0 && (c = qbgetc(up->oq)) != -1){
158*74a4d8c2SCharles.Forsyth if(predawn){
159*74a4d8c2SCharles.Forsyth while(up->txb->status & BDReady)
160*74a4d8c2SCharles.Forsyth ;
161*74a4d8c2SCharles.Forsyth } else {
162*74a4d8c2SCharles.Forsyth for(i = 0; i < 100; i++){
163*74a4d8c2SCharles.Forsyth if((up->txb->status & BDReady) == 0)
164*74a4d8c2SCharles.Forsyth break;
165*74a4d8c2SCharles.Forsyth delay(1);
166*74a4d8c2SCharles.Forsyth }
167*74a4d8c2SCharles.Forsyth }
168*74a4d8c2SCharles.Forsyth up->txbuf[0] = c;
169*74a4d8c2SCharles.Forsyth up->txb->length = 1;
170*74a4d8c2SCharles.Forsyth up->txb->status |= BDReady;
171*74a4d8c2SCharles.Forsyth up->txbusy = !predawn;
172*74a4d8c2SCharles.Forsyth }
173*74a4d8c2SCharles.Forsyth splx(s);
174*74a4d8c2SCharles.Forsyth }
175*74a4d8c2SCharles.Forsyth
176*74a4d8c2SCharles.Forsyth void
uartspecial(int port,int baud,Queue ** iq,Queue ** oq,void (* rx)(Queue *,int))177*74a4d8c2SCharles.Forsyth uartspecial(int port, int baud, Queue **iq, Queue **oq, void (*rx)(Queue*,int))
178*74a4d8c2SCharles.Forsyth {
179*74a4d8c2SCharles.Forsyth Uart *up = &uart[0];
180*74a4d8c2SCharles.Forsyth
181*74a4d8c2SCharles.Forsyth if(up->setup)
182*74a4d8c2SCharles.Forsyth return;
183*74a4d8c2SCharles.Forsyth up->setup = 1;
184*74a4d8c2SCharles.Forsyth
185*74a4d8c2SCharles.Forsyth *iq = up->iq = qopen(4*1024, 0, 0, 0);
186*74a4d8c2SCharles.Forsyth *oq = up->oq = qopen(16*1024, 0, uartkick, up);
187*74a4d8c2SCharles.Forsyth up->rx = rx;
188*74a4d8c2SCharles.Forsyth USED(port);
189*74a4d8c2SCharles.Forsyth up->port = SMC1ID;
190*74a4d8c2SCharles.Forsyth if(baud == 0)
191*74a4d8c2SCharles.Forsyth baud = 9600;
192*74a4d8c2SCharles.Forsyth smcsetup(up, baud);
193*74a4d8c2SCharles.Forsyth /* if using SCCn's UART, would also set DTR and RTS, but SMC doesn't use them */
194*74a4d8c2SCharles.Forsyth }
195*74a4d8c2SCharles.Forsyth
196*74a4d8c2SCharles.Forsyth void
uartsetboot(void (* f)(uchar *,int))197*74a4d8c2SCharles.Forsyth uartsetboot(void (*f)(uchar*, int))
198*74a4d8c2SCharles.Forsyth {
199*74a4d8c2SCharles.Forsyth uart[0].boot = f;
200*74a4d8c2SCharles.Forsyth }
201*74a4d8c2SCharles.Forsyth
202*74a4d8c2SCharles.Forsyth void
uartputs(char * s,int n)203*74a4d8c2SCharles.Forsyth uartputs(char *s, int n)
204*74a4d8c2SCharles.Forsyth {
205*74a4d8c2SCharles.Forsyth Uart *up = &uart[0];
206*74a4d8c2SCharles.Forsyth Block *b;
207*74a4d8c2SCharles.Forsyth int nl;
208*74a4d8c2SCharles.Forsyth char *p;
209*74a4d8c2SCharles.Forsyth
210*74a4d8c2SCharles.Forsyth nl = 0;
211*74a4d8c2SCharles.Forsyth for(p = s; p < s+n; p++)
212*74a4d8c2SCharles.Forsyth if(*p == '\n')
213*74a4d8c2SCharles.Forsyth nl++;
214*74a4d8c2SCharles.Forsyth b = iallocb(n+nl);
215*74a4d8c2SCharles.Forsyth while(n--){
216*74a4d8c2SCharles.Forsyth if(*s == '\n')
217*74a4d8c2SCharles.Forsyth *b->wp++ = '\r';
218*74a4d8c2SCharles.Forsyth *b->wp++ = *s++;
219*74a4d8c2SCharles.Forsyth }
220*74a4d8c2SCharles.Forsyth qbwrite(up->oq, b);
221*74a4d8c2SCharles.Forsyth }
222*74a4d8c2SCharles.Forsyth
223*74a4d8c2SCharles.Forsyth void
uartwait(void)224*74a4d8c2SCharles.Forsyth uartwait(void)
225*74a4d8c2SCharles.Forsyth {
226*74a4d8c2SCharles.Forsyth Uart *up = &uart[0];
227*74a4d8c2SCharles.Forsyth
228*74a4d8c2SCharles.Forsyth while(up->txbusy)
229*74a4d8c2SCharles.Forsyth ;
230*74a4d8c2SCharles.Forsyth }
231