FreeBSD/Linux Kernel Cross Reference
sys/sqt/slic.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1991 Carnegie Mellon University
4 * Copyright (c) 1991 Sequent Computer Systems
5 * All Rights Reserved.
6 *
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation.
12 *
13 * CARNEGIE MELLON AND SEQUENT COMPUTER SYSTEMS ALLOW FREE USE OF
14 * THIS SOFTWARE IN ITS "AS IS" CONDITION. CARNEGIE MELLON AND
15 * SEQUENT COMPUTER SYSTEMS DISCLAIM ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes.
27 */
28
29 /*
30 * HISTORY
31 * $Log: slic.c,v $
32 * Revision 2.3 91/07/31 18:03:48 dbg
33 * Changed copyright.
34 * [91/07/31 dbg]
35 *
36 * Revision 2.2 91/05/08 12:58:59 dbg
37 * Adapted for pure Mach kernel.
38 * [90/10/03 dbg]
39 *
40 */
41
42 #ifndef lint
43 static char rcsid[] = "$Header: slic.c,v 2.3 91/07/31 18:03:48 dbg Exp $";
44 #endif
45
46 #include <sqt/SGSproc.h>
47 #include <sqt/slic.h>
48 #include <sqt/intctl.h>
49
50 /*
51 * slic.c
52 * Slic functions.
53 *
54 * All routines assume caller arranged mutex of SLIC usage (splhi() or
55 * disable processor interrupts) -- SLIC registers are not save/restored
56 * across interrupts.
57 *
58 * Conditionals:
59 * -DCHECKSLIC check slic results (parity, etc) for sanity
60 *
61 * Gates are handled in gate.c; interrupt acceptence/etc in locore.s
62 */
63
64 /*
65 * Revision 1.2 89/07/20 18:05:24 kak
66 * moved balance includes
67 *
68 * Revision 1.1 89/07/05 13:15:46 kak
69 * Initial revision
70 *
71 */
72
73 void wrAddr(); /* forward */
74 void wrData(); /* forward */
75 int rdData(); /* forward */
76 spl_t lock_subslave(); /* forward */
77 void unlock_subslave(); /* forward */
78 /*
79 * wrslave()
80 * Write to a slave port.
81 *
82 * Note: this does no mutex on destination; assumes caller handles mutex
83 * if necessary. If done to "self" (eg, during initialization), no mutex
84 * necessary.
85 *
86 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
87 */
88
89 wrslave(destination, reg, data)
90 unsigned char destination, reg, data;
91 {
92 wrAddr(destination, reg);
93 wrData(destination, data);
94 }
95
96 /*
97 * rdslave()
98 * Read a slave port.
99 *
100 * Note: this does no mutex on destination; assumes caller handles mutex
101 * if necessary. If done to "self" (eg, during initialization), no mutex
102 * necessary.
103 *
104 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
105 */
106
107 int
108 rdslave(destination, reg)
109 unsigned char destination, reg;
110 {
111 wrAddr(destination, reg);
112 return(rdData(destination));
113 }
114
115 /*
116 * wrSubslave()
117 * Write a register that responds to SLIC slave sub-register addressing.
118 *
119 * Some slic/slave accesses for different resources are done thru the
120 * same SLIC shared (eg, SGS processor BIC); use a locking protocol
121 * on relevant slic/slave accesses.
122 *
123 * For compatibility with diagnostic usage, if slave==0 don't do the wrAddr().
124 *
125 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
126 */
127
128 wrSubslave(slic, slave, subreg, val)
129 u_char slic, slave, subreg, val;
130 {
131 spl_t s;
132
133 s = lock_subslave(slic, slave);
134
135 if (slave != 0)
136 wrAddr(slic, slave);
137 wrData(slic, subreg);
138 wrData(slic, val);
139
140 unlock_subslave(slic, slave, s);
141 }
142
143 /*
144 * rdSubslave()
145 * Read a register that responds to SLIC slave sub-register addressing.
146 *
147 * Some slic/slave accesses for different resources are done thru the
148 * same SLIC shared (eg, SGS processor BIC); use a locking protocol
149 * on relevant slic/slave accesses.
150 *
151 * For compatibility with diagnostic usage, if slave==0 don't do the wrAddr().
152 *
153 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
154 */
155
156 int
157 rdSubslave(slic, slave, subreg)
158 u_char slic, slave, subreg;
159 {
160 int val;
161 spl_t s;
162
163 s = lock_subslave(slic, slave);
164
165 if (slave != 0)
166 wrAddr(slic, slave);
167 wrData(slic, subreg);
168 val = rdData(slic);
169
170 unlock_subslave(slic, slave, s);
171
172 return (val);
173 }
174
175 /*
176 * wrAddr()
177 * Write address to slave.
178 *
179 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
180 */
181 void
182 wrAddr(destination, address)
183 unsigned char destination, address;
184 {
185 register struct cpuslic *sl = va_slic;
186
187 sl->sl_dest = destination;
188 sl->sl_smessage = address;
189 sl->sl_cmd_stat = SL_WRADDR;
190 while (sl->sl_cmd_stat & SL_BUSY)
191 continue;
192 #ifdef CHECKSLIC
193 check_slic("wrAddr");
194 #endif CHECKSLIC
195 }
196
197 /*
198 * wrData()
199 * Write data to previously addressed slave register.
200 *
201 * Internal interface.
202 *
203 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
204 */
205 void
206 wrData(destination, data)
207 unsigned char destination, data;
208 {
209 register struct cpuslic *sl = va_slic;
210
211 sl->sl_dest = destination;
212 sl->sl_smessage = data;
213 sl->sl_cmd_stat = SL_WRDATA;
214 while (sl->sl_cmd_stat & SL_BUSY)
215 continue;
216 #ifdef CHECKSLIC
217 check_slic("wrData");
218 #endif CHECKSLIC
219 }
220
221 /*
222 * rdData()
223 * Read data from previously addressed slave register.
224 *
225 * Internal interface.
226 *
227 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
228 */
229
230 int
231 rdData(destination)
232 unsigned char destination;
233 {
234 register struct cpuslic *sl = va_slic;
235
236 sl->sl_dest = destination;
237 sl->sl_cmd_stat = SL_RDDATA;
238 while (sl->sl_cmd_stat & SL_BUSY)
239 continue;
240 #ifdef CHECKSLIC
241 check_slic("rdData");
242 #endif CHECKSLIC
243 return(sl->sl_sdr & 0xff);
244 }
245
246 /*
247 * sendsoft()
248 * Post SW interrupt to somebody.
249 *
250 * Used to post resched "nudge", net handler interrupts, pff calc, softclock.
251 *
252 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
253 */
254
255 sendsoft(dest, bitmask)
256 unsigned char dest;
257 unsigned char bitmask;
258 {
259 register struct cpuslic *sl = va_slic;
260
261 sl->sl_dest = dest;
262 sl->sl_smessage = bitmask;
263
264 sl->sl_cmd_stat = SL_MINTR | 0; /* 0 ==> bin 0 */
265 while (sl->sl_cmd_stat & SL_BUSY)
266 continue;
267
268 #ifdef CHECKSLIC
269 check_slic("sendsoft");
270 #endif CHECKSLIC
271 }
272
273 /*
274 * nmIntr()
275 * Post NMI interrupt to somebody.
276 *
277 * Used to post send NMI to a processor to have it shut down.
278 *
279 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
280 */
281
282 nmIntr(dest, message)
283 unsigned char dest;
284 unsigned char message;
285 {
286 register struct cpuslic *sl = va_slic;
287
288 sl->sl_dest = dest;
289 sl->sl_smessage = message;
290
291 do {
292 sl->sl_cmd_stat = SL_NMINTR;
293 while (sl->sl_cmd_stat & SL_BUSY)
294 continue;
295 } while ((sl->sl_cmd_stat & SL_OK) == 0);
296 #ifdef CHECKSLIC
297 check_slic("nmIntr");
298 #endif CHECKSLIC
299 }
300
301 /*
302 * mIntr()
303 * Post HW interrupt to somebody.
304 *
305 * Used to send commands to MBAd's.
306 *
307 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
308 *
309 * Implementation acquires gate before sending message, to avoid SLIC bus
310 * saturation.
311 */
312
313 #ifdef PERFSTAT
314 #define MINTR_MAXHIST 65
315 int mintr_hist[MINTR_MAXHIST];
316 #endif PERFSTAT
317
318 mIntr(dest, bin, data)
319 unsigned char dest;
320 unsigned char bin;
321 unsigned char data;
322 {
323 register struct cpuslic *sl = va_slic;
324 register unsigned stat;
325 #ifdef PERFSTAT
326 register int mintr_cnt = 0;
327 #endif PERFSTAT
328
329 /*
330 * Send message. Spin forever until sent.
331 */
332
333 sl->sl_dest = dest;
334 sl->sl_smessage = data;
335
336 do {
337 #ifdef PERFSTAT
338 ++mintr_cnt;
339 #endif PERFSTAT
340 sl->sl_cmd_stat = SL_MINTR | bin;
341 while ((stat = sl->sl_cmd_stat) & SL_BUSY)
342 continue;
343 } while ((stat & SL_OK) == 0);
344
345 #ifdef PERFSTAT
346 if (mintr_cnt > MINTR_MAXHIST)
347 mintr_cnt = MINTR_MAXHIST;
348 ++mintr_hist[mintr_cnt-1];
349 #endif PERFSTAT
350
351 #ifdef CHECKSLIC
352 check_slic("mIntr");
353 #endif CHECKSLIC
354
355 /*
356 * Release mIntr gate.
357 */
358
359 }
360
361 /*
362 * setgm()
363 * Set group mask in destination slic.
364 *
365 * Caller assures mutex of SLIC usage (splhi() or holding gate is sufficient).
366 */
367
368 setgm(dest, mask)
369 unsigned char dest;
370 unsigned char mask;
371 {
372 register struct cpuslic *sl = va_slic;
373
374 sl->sl_dest = dest; /* set this guy's... */
375 sl->sl_smessage = mask; /* group mask to "mask" */
376 sl->sl_cmd_stat = SL_SETGM; /* set the group-mask */
377 while (sl->sl_cmd_stat & SL_BUSY) /* and wait for cmd done */
378 continue;
379
380 #ifdef CHECKSLIC
381 check_slic("setgm");
382 #endif CHECKSLIC
383 }
384
385 /*
386 * lock_subslave(), unlock_subslave()
387 * Mutex access to certain slic/sub-slave combinations which
388 * may be shared (eg, processor BIC -- both processors access
389 * the BIC via only one of their slic id's).
390 *
391 * Other uses of slic slave addressing is mutually excluded at higher levels;
392 * upper level code only online/offline's one processor at a time, memory
393 * error polling guaranteed single-thread, etc.
394 */
395
396 spl_t
397 lock_subslave(slic, slave)
398 unsigned char slic, slave;
399 {
400 return 0;
401 }
402
403 void
404 unlock_subslave(slic, slave, s)
405 unsigned char slic, slave;
406 spl_t s;
407 {
408 }
409
410 #ifdef CHECKSLIC
411 /*
412 * check_slic()
413 * Check status from SLIC for parity, exists, and ok bits.
414 */
415
416 check_slic(procname)
417 char *procname;
418 {
419 register unsigned stat;
420
421 stat = va_slic->sl_cmd_stat;
422
423 if ((stat & SL_PARITY) == 0) {
424 printf("%s: slic parity error\n", procname);
425 panic("slic");
426 /*NOTREACHED*/
427 }
428 if ((stat & SL_EXISTS) == 0) {
429 printf("%s: slic(s) don't exist\n", procname);
430 panic("slic");
431 /*NOTREACHED*/
432 }
433 if ((stat & SL_OK) == 0) {
434 printf("%s: slic not ok\n", procname);
435 panic("slic");
436 /*NOTREACHED*/
437 }
438 }
439 #endif CHECKSLIC
Cache object: f4e08ec5e57df313af1b2852c9d93bb6
|