Annotation of sys/arch/hppa64/stand/libsa/pdc.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: pdc.c,v 1.1 2005/04/01 10:40:48 mickey Exp $ */
2:
3: /*
4: * Copyright (c) 2005 Michael Shalayeff
5: * All rights reserved.
6: *
7: * Permission to use, copy, modify, and distribute this software for any
8: * purpose with or without fee is hereby granted, provided that the above
9: * copyright notice and this permission notice appear in all copies.
10: *
11: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15: * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
16: * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19: /*
20: * Copyright 1996 1995 by Open Software Foundation, Inc.
21: * All Rights Reserved
22: *
23: * Permission to use, copy, modify, and distribute this software and
24: * its documentation for any purpose and without fee is hereby granted,
25: * provided that the above copyright notice appears in all copies and
26: * that both the copyright notice and this permission notice appear in
27: * supporting documentation.
28: *
29: * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
30: * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31: * FOR A PARTICULAR PURPOSE.
32: *
33: * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
34: * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
35: * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
36: * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
37: * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38: *
39: */
40: /*
41: * Copyright (c) 1990 mt Xinu, Inc. All rights reserved.
42: * Copyright (c) 1990 University of Utah. All rights reserved.
43: *
44: * This file may be freely distributed in any form as long as
45: * this copyright notice is included.
46: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
47: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
48: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
49: *
50: * Utah $Hdr: pdc.c 1.8 92/03/14$
51: */
52:
53: #include <sys/time.h>
54: #include "libsa.h"
55: #include <sys/reboot.h>
56: #include <sys/disklabel.h>
57:
58: #include <machine/trap.h>
59: #include <machine/pdc.h>
60: #include <machine/iomod.h>
61: #include <machine/nvm.h>
62: #include <machine/param.h>
63: #include <machine/cpufunc.h>
64:
65: #include "dev_hppa64.h"
66:
67: /*
68: * Interface routines to initialize and access the PDC.
69: */
70:
71: pdcio_t pdc;
72: int pdcbuf[64] PDC_ALIGNMENT;/* PDC return buffer */
73: struct stable_storage sstor; /* contents of Stable Storage */
74: int sstorsiz; /* size of Stable Storage */
75: struct bootdata bd;
76: int bdsize = sizeof(struct bootdata);
77:
78: /*
79: * Initialize PDC and related variables.
80: */
81: void
82: pdc_init()
83: {
84: int err;
85:
86: /*
87: * Initialize important global variables (defined above).
88: */
89: pdc = (pdcio_t)(u_long)PAGE0->mem_pdc;
90:
91: err = pdc_call(pdc, PDC_STABLE, PDC_STABLE_SIZE, pdcbuf, 0, 0);
92: if (err >= 0) {
93: sstorsiz = min(pdcbuf[0],sizeof(sstor));
94: err = (*pdc)(PDC_STABLE, PDC_STABLE_READ, 0, &sstor, sstorsiz);
95: }
96:
97: /*
98: * Now that we (may) have an output device, if we encountered
99: * an error reading Stable Storage (above), let them know.
100: */
101: #ifdef DEBUG
102: if (debug && err)
103: printf("Stable storage PDC_STABLE Read Ret'd %d\n", err);
104: #endif
105:
106: /*
107: * Clear the FAULT light (so we know when we get a real one)
108: */
109: pdc_call(pdc, PDC_CHASSIS, PDC_CHASSIS_DISP,
110: PDC_OSTAT(PDC_OSTAT_BOOT) | 0xCEC0);
111: }
112:
113: /*
114: * Generic READ/WRITE through IODC. Takes pointer to PDC device
115: * information, returns (positive) number of bytes actually read or
116: * the (negative) error condition, or zero if at "EOF".
117: */
118: int
119: iodcstrategy(devdata, rw, blk, size, buf, rsize)
120: void *devdata;
121: int rw;
122: daddr_t blk;
123: size_t size;
124: void *buf;
125: size_t *rsize;
126: {
127: struct hppa_dev *dp = devdata;
128: struct pz_device *pzdev = dp->pz_dev;
129: iodcio_t iodc = (iodcio_t)(u_long)pzdev->pz_iodc_io;
130: int offset, xfer, ret;
131:
132: #ifdef PDCDEBUG
133: if (debug)
134: printf("iodcstrategy(%p, %s, %u, %u, %p, %p)\n", devdata,
135: rw==F_READ? "READ" : "WRITE", blk, size, buf, rsize);
136:
137: if (debug > 1)
138: PZDEV_PRINT(pzdev);
139: #endif
140:
141: blk += dp->fsoff;
142: blk <<= DEV_BSHIFT;
143: if ((pzdev->pz_class & PCL_CLASS_MASK) == PCL_SEQU) {
144: /* rewind and re-read to seek */
145: if (blk < dp->last_blk) {
146: #ifdef PDCDEBUG
147: if (debug)
148: printf("iodc: rewind ");
149: #endif
150: if ((ret = ((iodcio_t)(long)pzdev->pz_iodc_io)(
151: pzdev->pz_hpa, IODC_IO_READ, pzdev->pz_spa,
152: pzdev->pz_layers, pdcbuf, 0, dp->buf, 0, 0)) < 0) {
153: #ifdef DEBUG
154: if (debug)
155: printf("IODC_IO: %d\n", ret);
156: #endif
157: return (EIO);
158: } else {
159: dp->last_blk = 0;
160: dp->last_read = 0;
161: }
162: }
163:
164: #ifdef PDCDEBUG
165: if (debug)
166: printf("seek %d ", dp->last_blk);
167: #endif
168: for (; (dp->last_blk + dp->last_read) <= blk;
169: dp->last_read = ret) {
170: twiddle();
171: dp->last_blk += dp->last_read;
172: if ((ret = (iodc)(pzdev->pz_hpa,
173: IODC_IO_READ, pzdev->pz_spa, pzdev->pz_layers,
174: pdcbuf, dp->last_blk, dp->buf, IODC_IOSIZ,
175: IODC_IOSIZ)) < 0) {
176: #ifdef DEBUG
177: if (debug)
178: printf("IODC_IO: %d\n", ret);
179: #endif
180: return (EIO);
181: }
182: if ((ret = pdcbuf[0]) == 0)
183: break;
184: #ifdef PDCDEBUG
185: if (debug)
186: printf("-");
187: #endif
188: }
189: #ifdef PDCDEBUG
190: if (debug)
191: printf("> %d[%d]\n", dp->last_blk, dp->last_read);
192: #endif
193: }
194:
195: xfer = 0;
196: /* see if we can scratch anything from buffer */
197: if (dp->last_blk <= blk && (dp->last_blk + dp->last_read) > blk) {
198: twiddle();
199: offset = blk - dp->last_blk;
200: xfer = min(dp->last_read - offset, size);
201: size -= xfer;
202: blk += xfer;
203: #ifdef PDCDEBUG
204: if (debug)
205: printf("off=%d,xfer=%d,size=%d,blk=%d\n",
206: offset, xfer, size, blk);
207: #endif
208: bcopy(dp->buf + offset, buf, xfer);
209: buf += xfer;
210: }
211:
212: /*
213: * double buffer it all the time, to cache
214: */
215: for (; size; size -= ret, buf += ret, blk += ret, xfer += ret) {
216: offset = blk & IOPGOFSET;
217: if ((ret = (iodc)(pzdev->pz_hpa,
218: (rw == F_READ? IODC_IO_READ: IODC_IO_WRITE),
219: pzdev->pz_spa, pzdev->pz_layers, pdcbuf,
220: blk - offset, dp->buf, IODC_IOSIZ, IODC_IOSIZ)) < 0) {
221: #ifdef DEBUG
222: if (debug)
223: printf("iodc_read(%d,%d): %d\n",
224: blk - offset, IODC_IOSIZ, ret);
225: #endif
226: if (xfer)
227: break;
228: else
229: return (EIO);
230: }
231: if ((ret = pdcbuf[0]) <= 0)
232: break;
233: dp->last_blk = blk - offset;
234: dp->last_read = ret;
235: if ((ret -= offset) > size)
236: ret = size;
237: bcopy(dp->buf + offset, buf, ret);
238: #ifdef PDCDEBUG
239: if (debug)
240: printf("read %d(%d,%d)@%x ", ret,
241: dp->last_blk, dp->last_read, (u_int)buf);
242: #endif
243: }
244:
245: #ifdef PDCDEBUG
246: if (debug)
247: printf("\n");
248: #endif
249:
250: if (rsize)
251: *rsize = xfer;
252: return (0);
253: }
254:
255: /*
256: * Find a device with specified unit number
257: * (any if unit == -1), and of specified class (PCL_*).
258: */
259: struct pz_device *
260: pdc_findev(unit, class)
261: int unit, class;
262: {
263: static struct pz_device pz;
264: int layers[sizeof(pz.pz_layers)/sizeof(pz.pz_layers[0])];
265: iodcio_t iodc;
266: int err = 0;
267: u_int hpa, spa;
268:
269: #ifdef PDCDEBUG
270: if (debug)
271: printf("pdc_finddev(%d, %x)\n", unit, class);
272: #endif
273: iodc = (iodcio_t)((u_long)PAGE0->mem_free + IODC_MAXSIZE);
274: hpa = PAGE0->mem_boot.pz_hpa;
275: spa = ((struct iomod *)(u_long)hpa)->io_spa;
276:
277: /* quick hack for boot device */
278: if (PAGE0->mem_boot.pz_class == class &&
279: (unit == -1 || PAGE0->mem_boot.pz_layers[0] == unit)) {
280:
281: bcopy (&PAGE0->mem_boot.pz_dp, &pz.pz_dp, sizeof(pz.pz_dp));
282: bcopy (pz.pz_layers, layers, sizeof(layers));
283: if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, hpa,
284: IODC_INIT, iodc, IODC_MAXSIZE)) < 0) {
285: #ifdef DEBUG
286: if (debug)
287: printf("IODC_READ: %d\n", err);
288: #endif
289: return NULL;
290: }
291: } else {
292: struct pdc_memmap memmap;
293: struct iodc_data mptr;
294: int i, stp;
295:
296: for (i = 0; i < 0xf; i++) {
297: pz.pz_bc[0] = pz.pz_bc[1] =
298: pz.pz_bc[2] = pz.pz_bc[3] = -1;
299: pz.pz_bc[4] = 2;
300: pz.pz_bc[5] = 0; /* core bus */
301: pz.pz_mod = i;
302: if ((pdc)(PDC_MEMMAP, PDC_MEMMAP_HPA, &memmap,
303: &pz.pz_dp) < 0)
304: continue;
305: #ifdef PDCDEBUG
306: if (debug)
307: printf("memap: %d.%d.%d, hpa=%x, mpgs=%x\n",
308: pz.pz_bc[4], pz.pz_bc[5], pz.pz_mod,
309: memmap.hpa, memmap.morepages);
310: #endif
311: hpa = memmap.hpa;
312:
313: if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, &pdcbuf, hpa,
314: IODC_DATA, &mptr, sizeof(mptr))) < 0) {
315: #ifdef DEBUG
316: if (debug)
317: printf("IODC_DATA: %d\n", err);
318: #endif
319: continue;
320: }
321:
322: if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, hpa,
323: IODC_INIT, iodc, IODC_MAXSIZE)) < 0) {
324: #ifdef DEBUG
325: if (debug)
326: printf("IODC_READ: %d\n", err);
327: #endif
328: continue;
329: }
330:
331: stp = IODC_INIT_FIRST;
332: do {
333: if ((err = (iodc)(hpa, stp, spa, layers,
334: pdcbuf, 0, 0, 0, 0)) < 0) {
335: #ifdef DEBUG
336: if (debug && err != PDC_ERR_EOD)
337: printf("IODC_INIT_%s: %d\n",
338: stp==IODC_INIT_FIRST?
339: "FIRST":"NEXT", err);
340: #endif
341: break;
342: }
343: #ifdef PDCDEBUG
344: if (debug)
345: printf("[%x,%x,%x,%x,%x,%x], "
346: "[%x,%x,%x,%x,%x,%x]\n",
347: pdcbuf[0], pdcbuf[1], pdcbuf[2],
348: pdcbuf[3], pdcbuf[4], pdcbuf[5],
349: layers[0], layers[1], layers[2],
350: layers[3], layers[4], layers[5]);
351: #endif
352: stp = IODC_INIT_NEXT;
353:
354: } while (pdcbuf[1] != class &&
355: unit != -1 && unit != layers[0]);
356:
357: if (err >= 0)
358: break;
359: }
360: }
361:
362: if (err >= 0) {
363: /* init device */
364: if (0 && (err = (iodc)(hpa, IODC_INIT_DEV, spa,
365: layers, pdcbuf, 0, 0, 0, 0)) < 0) {
366: #ifdef DEBUG
367: if (debug)
368: printf("INIT_DEV: %d\n", err);
369: #endif
370: return NULL;
371: }
372:
373: /* read i/o entry code */
374: if ((err = (pdc)(PDC_IODC, PDC_IODC_READ, pdcbuf, hpa,
375: IODC_IO, iodc, IODC_MAXSIZE)) < 0) {
376: #ifdef DEBUG
377: if (debug)
378: printf("IODC_READ: %d\n", err);
379: #endif
380: return NULL;
381: }
382:
383: pz.pz_flags = 0;
384: bcopy(layers, pz.pz_layers, sizeof(pz.pz_layers));
385: pz.pz_hpa = hpa;
386: /* XXX pz.pz_spa = spa; */
387: pz.pz_iodc_io = (u_long)iodc;
388: pz.pz_class = class;
389:
390: return &pz;
391: }
392:
393: return NULL;
394: }
395:
396: static __inline void
397: fall(int c_base, int c_count, int c_loop, int c_stride, int data)
398: {
399: int loop; /* Internal vars */
400:
401: for (; c_count--; c_base += c_stride)
402: for (loop = c_loop; loop--; )
403: if (data)
404: fdce(0, c_base);
405: else
406: fice(0, c_base);
407: }
408:
409: /*
410: * fcacheall - Flush all caches.
411: *
412: * This routine is just a wrapper around the real cache flush routine.
413: */
414: struct pdc_cache pdc_cacheinfo PDC_ALIGNMENT;
415:
416: void
417: fcacheall()
418: {
419: int err;
420:
421: if ((err = (*pdc)(PDC_CACHE, PDC_CACHE_DFLT, &pdc_cacheinfo)) < 0) {
422: #ifdef DEBUG
423: if (debug)
424: printf("fcacheall: PDC_CACHE failed (%d).\n", err);
425: #endif
426: return;
427: }
428: #if PDCDEBUG
429: if (debug)
430: printf("pdc_cache:\nic={%u,%x,%x,%u,%u,%u}\n"
431: "dc={%u,%x,%x,%u,%u,%u}\n",
432: pdc_cacheinfo.ic_size, *(u_int *)&pdc_cacheinfo.ic_conf,
433: pdc_cacheinfo.ic_base, pdc_cacheinfo.ic_stride,
434: pdc_cacheinfo.ic_count, pdc_cacheinfo.ic_loop,
435: pdc_cacheinfo.dc_size, *(u_int *)&pdc_cacheinfo.ic_conf,
436: pdc_cacheinfo.dc_base, pdc_cacheinfo.dc_stride,
437: pdc_cacheinfo.dc_count, pdc_cacheinfo.dc_loop);
438: #endif
439: /*
440: * Flush the instruction, then data cache.
441: */
442: fall(pdc_cacheinfo.ic_base, pdc_cacheinfo.ic_count,
443: pdc_cacheinfo.ic_loop, pdc_cacheinfo.ic_stride, 0);
444: sync_caches();
445: fall(pdc_cacheinfo.dc_base, pdc_cacheinfo.dc_count,
446: pdc_cacheinfo.dc_loop, pdc_cacheinfo.dc_stride, 1);
447: sync_caches();
448: }
CVSweb