xref: /inferno-os/os/boot/rpcg/cpm.c (revision 9dc22068e29604f4b484e746112a9a4efe6fd57f)
1 #include "u.h"
2 #include "lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7 
8 enum {
9 	BDSIZE=	1024,	/* TO DO: check this */
10 };
11 
12 static	Map	bdmapv[BDSIZE/sizeof(BD)];
13 static	RMap	bdmap = {"buffer descriptors"};
14 
15 void
16 cpminit(void)
17 {
18 	IMM *io;
19 
20 	io = m->iomem;
21 	io->sdcr = 1;
22 	io->lccr &= ~1;	/* disable LCD */
23 	io->pcint = 0;	/* disable all port C interrupts */
24 	io->pcso = 0;
25 	io->pcdir =0;
26 	io->pcpar = 0;
27 	io->pcdat = 0;
28 	io->papar = 0;
29 	io->padir = 0;
30 	io->paodr = 0;
31 	io->padat = 0;
32 	io->pbpar = 0;
33 	io->pbdir = 0;
34 	io->pbodr = 0;
35 	io->pbdat = 0;
36 	eieio();
37 
38 	for(io->cpcr = 0x8001; io->cpcr & 1;)	/* reset all CPM channels */
39 		eieio();
40 
41 	mapinit(&bdmap, bdmapv, sizeof(bdmapv));
42 	mapfree(&bdmap, DPBASE, BDSIZE);
43 }
44 
45 void
46 cpmop(int op, int cno, int param)
47 {
48 	IMM *io;
49 	int s;
50 
51 	s = splhi();
52 	io = m->iomem;
53 	eieio();
54 	while(io->cpcr & 1)
55 		eieio();
56 	io->cpcr = (op<<8)|(cno<<4)|(param<<1)|1;
57 	eieio();
58 	while(io->cpcr & 1)
59 		eieio();
60 	splx(s);
61 }
62 
63 /*
64  * connect SCCx clocks in NSMI mode (x=1 for USB)
65  */
66 void
67 sccnmsi(int x, int rcs, int tcs)
68 {
69 	IMM *io;
70 	ulong v;
71 	int sh;
72 
73 	sh = (x-1)*8;	/* each SCCx field in sicr is 8 bits */
74 	v = (((rcs&7)<<3) | (tcs&7)) << sh;
75 	io = ioplock();
76 	io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
77 	iopunlock();
78 }
79 
80 void
81 scc2stop(void)
82 {
83 	SCC *scc;
84 
85 	scc = IOREGS(0xA20, SCC);
86 	if(scc->gsmrl & (3<<4)){
87 		cpmop(GracefulStopTx, SCC2ID, 0);
88 		cpmop(CloseRxBD, SCC2ID, 0);
89 		delay(1);
90 		scc->gsmrl &= ~(3<<4);	/* disable current use */
91 		archetherdisable(SCC2ID);
92 	}
93 }
94 
95 BD *
96 bdalloc(int n)
97 {
98 	ulong a;
99 
100 	a = mapalloc(&bdmap, 0, n*sizeof(BD), 0);
101 	if(a == 0)
102 		panic("bdalloc");
103 	return KADDR(a);
104 }
105 
106 void
107 bdfree(BD *b, int n)
108 {
109 	if(b){
110 		eieio();
111 		mapfree(&bdmap, PADDR(b), n*sizeof(BD));
112 	}
113 }
114 
115 /*
116  * initialise receive and transmit buffer rings.
117  */
118 int
119 ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
120 {
121 	int i, x;
122 
123 	/* the ring entries must be aligned on sizeof(BD) boundaries */
124 	r->nrdre = nrdre;
125 	if(r->rdr == nil)
126 		r->rdr = bdalloc(nrdre);
127 	/* the buffer size must align with cache lines since the cache doesn't snoop */
128 	bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
129 	if(r->rrb == nil)
130 		r->rrb = malloc(nrdre*bufsize);
131 	if(r->rdr == nil || r->rrb == nil)
132 		return -1;
133 	dcflush(r->rrb, nrdre*bufsize);
134 	x = PADDR(r->rrb);
135 	for(i = 0; i < nrdre; i++){
136 		r->rdr[i].length = 0;
137 		r->rdr[i].addr = x;
138 		r->rdr[i].status = BDEmpty|BDInt;
139 		x += bufsize;
140 	}
141 	r->rdr[i-1].status |= BDWrap;
142 	r->rdrx = 0;
143 
144 	r->ntdre = ntdre;
145 	if(r->tdr == nil)
146 		r->tdr = bdalloc(ntdre);
147 	if(r->txb == nil)
148 		r->txb = malloc(ntdre*sizeof(Block*));
149 	if(r->tdr == nil || r->txb == nil)
150 		return -1;
151 	for(i = 0; i < ntdre; i++){
152 		r->txb[i] = nil;
153 		r->tdr[i].addr = 0;
154 		r->tdr[i].length = 0;
155 		r->tdr[i].status = 0;
156 	}
157 	r->tdr[i-1].status |= BDWrap;
158 	r->tdrh = 0;
159 	r->tdri = 0;
160 	r->ntq = 0;
161 	return 0;
162 }
163