1 /* $NetBSD: pdc.c,v 1.11 2009/10/26 19:16:55 cegger Exp $ */
3 /* $OpenBSD: pdc.c,v 1.10 1999/05/06 02:27:44 mickey Exp $ */
6 * Copyright (c) 1998-2004 Michael Shalayeff
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
31 * Copyright 1996 1995 by Open Software Foundation, Inc.
34 * Permission to use, copy, modify, and distribute this software and
35 * its documentation for any purpose and without fee is hereby granted,
36 * provided that the above copyright notice appears in all copies and
37 * that both the copyright notice and this permission notice appear in
38 * supporting documentation.
40 * OSF DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
41 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
42 * FOR A PARTICULAR PURPOSE.
44 * IN NO EVENT SHALL OSF BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
45 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
46 * LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
47 * NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
48 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
52 * Copyright (c) 1990 mt Xinu, Inc. All rights reserved.
53 * Copyright (c) 1990 University of Utah. All rights reserved.
55 * This file may be freely distributed in any form as long as
56 * this copyright notice is included.
57 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
58 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
59 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
61 * Utah $Hdr: pdc.c 1.8 92/03/14$
66 #include <sys/reboot.h>
67 #include <sys/disklabel.h>
69 #include <machine/trap.h>
70 #include <machine/pdc.h>
71 #include <machine/iomod.h>
72 #include <machine/nvm.h>
73 #include <machine/param.h>
74 #include <machine/cpufunc.h>
79 * Interface routines to initialize and access the PDC.
83 int pdcbuf
[64] PDC_ALIGNMENT
;/* PDC return buffer */
84 struct stable_storage sstor
; /* contents of Stable Storage */
85 int sstorsiz
; /* size of Stable Storage */
87 int bdsize
= sizeof(struct bootdata
);
90 * Initialize PDC and related variables.
98 * Initialize important global variables (defined above).
100 pdc
= (pdcio_t
)PAGE0
->mem_pdc
;
102 err
= (*pdc
)(PDC_STABLE
, PDC_STABLE_SIZE
, pdcbuf
, 0, 0);
104 sstorsiz
= min(pdcbuf
[0],sizeof(sstor
));
105 err
= (*pdc
)(PDC_STABLE
, PDC_STABLE_READ
, 0, &sstor
, sstorsiz
);
109 * Now that we (may) have an output device, if we encountered
110 * an error reading Stable Storage (above), let them know.
114 printf("Stable storage PDC_STABLE Read Ret'd %d\n", err
);
118 * Clear the FAULT light (so we know when we get a real one)
120 (void) (*pdc
)(PDC_CHASSIS
, PDC_CHASSIS_DISP
,
121 PDC_OSTAT(PDC_OSTAT_BOOT
) | 0xCEC0);
125 * Generic READ/WRITE through IODC. Takes pointer to PDC device
126 * information, returns (positive) number of bytes actually read or
127 * the (negative) error condition, or zero if at "EOF".
130 iodcstrategy(void *devdata
, int rw
, daddr_t blk
, size_t size
, void *buf
,
133 struct hppa_dev
*dp
= devdata
;
134 struct pz_device
*pzdev
= dp
->pz_dev
;
135 int offset
, xfer
, ret
;
139 printf("iodcstrategy(%p, %s, %u, %u, %p, %p)\n", devdata
,
140 rw
==F_READ
?"READ":"WRITE", (unsigned) blk
, (unsigned) size
, buf
, rsize
);
148 if ((pzdev
->pz_class
& PCL_CLASS_MASK
) == PCL_SEQU
) {
149 /* rewind and re-read to seek */
150 if (blk
< dp
->last_blk
) {
153 printf("iodc: rewind ");
156 if ((ret
= (pzdev
->pz_iodc_io
)(pzdev
->pz_hpa
,
157 IODC_IO_READ
, pzdev
->pz_spa
, pzdev
->pz_layers
,
158 pdcbuf
, 0, dp
->buf
, 0, 0)) < 0) {
161 printf("IODC_IO: %d\n", ret
);
172 printf("seek %d ", (int) dp
->last_blk
);
174 for (; (dp
->last_blk
+ dp
->last_read
) <= blk
;
175 dp
->last_read
= ret
) {
177 dp
->last_blk
+= dp
->last_read
;
178 if ((ret
= (pzdev
->pz_iodc_io
)(pzdev
->pz_hpa
,
179 IODC_IO_READ
, pzdev
->pz_spa
, pzdev
->pz_layers
,
180 pdcbuf
, (unsigned) dp
->last_blk
, dp
->buf
, IODC_MAXIOSIZ
,
181 IODC_MAXIOSIZ
)) < 0) {
184 printf("IODC_IO: %d\n", ret
);
188 if ((ret
= pdcbuf
[0]) == 0)
197 printf("> %d[%d]\n", (int)dp
->last_blk
, (int)dp
->last_read
);
202 /* see if we can scratch anything from buffer */
203 if (dp
->last_blk
<= blk
&& (dp
->last_blk
+ dp
->last_read
) > blk
) {
205 offset
= blk
- dp
->last_blk
;
206 xfer
= min(dp
->last_read
- offset
, size
);
211 printf("off=%d,xfer=%d,size=%d,blk=%d\n",
212 offset
, xfer
, (int)size
, (int)blk
);
214 memcpy(buf
, dp
->buf
+ offset
, xfer
);
215 buf
= (char *) buf
+ xfer
;
219 * double buffer it all the time, to cache
222 size
-= ret
, buf
= (char *) buf
+ ret
, blk
+= ret
, xfer
+= ret
) {
224 offset
= blk
& IOPGOFSET
;
225 if ((ret
= (pzdev
->pz_iodc_io
)(pzdev
->pz_hpa
,
226 (rw
== F_READ
? IODC_IO_READ
: IODC_IO_WRITE
),
227 pzdev
->pz_spa
, pzdev
->pz_layers
, pdcbuf
,
228 (int)blk
- offset
, dp
->buf
, IODC_MAXIOSIZ
,
229 IODC_MAXIOSIZ
)) < 0) {
232 printf("iodc_read(%d,%d): %d\n",
233 (int)blk
- offset
, IODC_MAXIOSIZ
, ret
);
240 if ((ret
= pdcbuf
[0]) <= 0)
242 dp
->last_blk
= blk
- offset
;
244 if ((ret
-= offset
) > size
)
246 memcpy(buf
, dp
->buf
+ offset
, ret
);
249 printf("read %d(%d,%d)@%x ", ret
,
250 (int)dp
->last_blk
, (int)dp
->last_read
, (u_int
)buf
);
265 * Find a device with specified unit number
266 * (any if unit == -1), and of specified class (PCL_*).
269 pdc_findev(int unit
, int class)
271 static struct pz_device pz
;
272 int layers
[sizeof(pz
.pz_layers
)/sizeof(pz
.pz_layers
[0])];
279 printf("pdc_finddev(%d, %x)\n", unit
, class);
281 iodc
= (iodcio_t
)(PAGE0
->mem_free
+ IODC_MAXSIZE
);
282 io
= PAGE0
->mem_boot
.pz_hpa
;
284 /* quick hack for boot device */
285 if (PAGE0
->mem_boot
.pz_class
== class &&
286 (unit
== -1 || PAGE0
->mem_boot
.pz_layers
[0] == unit
)) {
288 bcopy (&PAGE0
->mem_boot
.pz_dp
, &pz
.pz_dp
, sizeof(pz
.pz_dp
));
289 bcopy (pz
.pz_layers
, layers
, sizeof(layers
));
290 if ((err
= (pdc
)(PDC_IODC
, PDC_IODC_READ
, pdcbuf
, io
,
291 IODC_INIT
, iodc
, IODC_MAXSIZE
)) < 0) {
294 printf("IODC_READ: %d\n", err
);
299 struct pdc_memmap memmap
;
300 struct iodc_data mptr
;
303 for (i
= 0; i
< 0xf; i
++) {
304 pz
.pz_bc
[0] = pz
.pz_bc
[1] =
305 pz
.pz_bc
[2] = pz
.pz_bc
[3] = -1;
307 pz
.pz_bc
[5] = 0; /* core bus */
309 if ((pdc
)(PDC_MEMMAP
, PDC_MEMMAP_HPA
, &memmap
,
314 printf("memap: %d.%d.%d, hpa=%x, mpgs=%x\n",
315 pz
.pz_bc
[4], pz
.pz_bc
[5], pz
.pz_mod
,
316 memmap
.hpa
, memmap
.morepages
);
318 io
= (struct iomod
*) memmap
.hpa
;
320 if ((err
= (pdc
)(PDC_IODC
, PDC_IODC_READ
, &pdcbuf
, io
,
321 IODC_DATA
, &mptr
, sizeof(mptr
))) < 0) {
324 printf("IODC_DATA: %d\n", err
);
329 if ((err
= (pdc
)(PDC_IODC
, PDC_IODC_READ
, pdcbuf
, io
,
330 IODC_INIT
, iodc
, IODC_MAXSIZE
)) < 0) {
333 printf("IODC_READ: %d\n", err
);
338 stp
= IODC_INIT_FIRST
;
340 if ((err
= (iodc
)(io
, stp
, io
->io_spa
, layers
,
341 pdcbuf
, 0, 0, 0, 0)) < 0) {
343 if (debug
&& err
!= PDC_ERR_EOD
)
344 printf("IODC_INIT_%s: %d\n",
345 stp
==IODC_INIT_FIRST
?
346 "FIRST":"NEXT", err
);
352 printf("[%x,%x,%x,%x,%x,%x], "
353 "[%x,%x,%x,%x,%x,%x]\n",
354 pdcbuf
[0], pdcbuf
[1], pdcbuf
[2],
355 pdcbuf
[3], pdcbuf
[4], pdcbuf
[5],
356 layers
[0], layers
[1], layers
[2],
357 layers
[3], layers
[4], layers
[5]);
359 stp
= IODC_INIT_NEXT
;
361 } while (pdcbuf
[1] != class &&
362 unit
!= -1 && unit
!= layers
[0]);
371 if (0 && (err
= (iodc
)(io
, IODC_INIT_DEV
, io
->io_spa
,
372 layers
, pdcbuf
, 0, 0, 0, 0)) < 0) {
375 printf("INIT_DEV: %d\n", err
);
380 /* read i/o entry code */
381 if ((err
= (pdc
)(PDC_IODC
, PDC_IODC_READ
, pdcbuf
, io
,
382 IODC_IO
, iodc
, IODC_MAXSIZE
)) < 0) {
385 printf("IODC_READ: %d\n", err
);
391 memcpy(pz
.pz_layers
, layers
, sizeof(pz
.pz_layers
));
393 /* XXX pz.pz_spa = io->io_spa; */
394 pz
.pz_iodc_io
= iodc
;
404 fall(int c_base
, int c_count
, int c_loop
, int c_stride
, int data
)
408 for (; c_count
--; c_base
+= c_stride
)
409 for (loop
= c_loop
; loop
--; )
418 * fcacheall - Flush all caches.
420 * This routine is just a wrapper around the real cache flush routine.
422 struct pdc_cache pdc_cacheinfo PDC_ALIGNMENT
;
429 if ((err
= (*pdc
)(PDC_CACHE
, PDC_CACHE_DFLT
, &pdc_cacheinfo
)) < 0) {
432 printf("fcacheall: PDC_CACHE failed (%d).\n", err
);
438 printf("pdc_cache:\nic={%u,%x,%x,%u,%u,%u}\n"
439 "dc={%u,%x,%x,%u,%u,%u}\n",
440 pdc_cacheinfo
.ic_size
, *(u_int
*)&pdc_cacheinfo
.ic_conf
,
441 pdc_cacheinfo
.ic_base
, pdc_cacheinfo
.ic_stride
,
442 pdc_cacheinfo
.ic_count
, pdc_cacheinfo
.ic_loop
,
443 pdc_cacheinfo
.dc_size
, *(u_int
*)&pdc_cacheinfo
.ic_conf
,
444 pdc_cacheinfo
.dc_base
, pdc_cacheinfo
.dc_stride
,
445 pdc_cacheinfo
.dc_count
, pdc_cacheinfo
.dc_loop
);
448 * Flush the instruction, then data cache.
450 fall(pdc_cacheinfo
.ic_base
, pdc_cacheinfo
.ic_count
,
451 pdc_cacheinfo
.ic_loop
, pdc_cacheinfo
.ic_stride
, 0);
453 fall(pdc_cacheinfo
.dc_base
, pdc_cacheinfo
.dc_count
,
454 pdc_cacheinfo
.dc_loop
, pdc_cacheinfo
.dc_stride
, 1);