1 /* $NetBSD: mem.c,v 1.20 2009/05/08 09:33:58 skrll Exp $ */
3 /* $OpenBSD: mem.c,v 1.30 2007/09/22 16:21:32 krw Exp $ */
5 * Copyright (c) 1998-2004 Michael Shalayeff
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27 * THE POSSIBILITY OF SUCH DAMAGE.
30 * Copyright (c) 1991,1992,1994, The University of Utah and
31 * the Computer Systems Laboratory (CSL). All rights reserved.
33 * Subject to your agreements with CMU,
34 * permission to use, copy, modify and distribute this software and its
35 * documentation is hereby granted, provided that both the copyright
36 * notice and this permission notice appear in all copies of the
37 * software, derivative works or modified versions, and any portions
38 * thereof, and that both notices appear in supporting documentation.
40 * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
41 * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
42 * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
44 * CSL requests users of this software to return to csl-dist@cs.utah.edu any
45 * improvements that they make and grant CSL redistribution rights.
47 * Utah $Hdr: mem.c 1.9 94/12/16$
50 * Mach Operating System
51 * Copyright (c) 1992 Carnegie Mellon University
52 * All Rights Reserved.
54 * Permission to use, copy, modify and distribute this software and its
55 * documentation is hereby granted, provided that both the copyright
56 * notice and this permission notice appear in all copies of the
57 * software, derivative works or modified versions, and any portions
58 * thereof, and that both notices appear in supporting documentation.
60 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
61 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
62 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
64 * Carnegie Mellon requests users of this software to return to
66 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
67 * School of Computer Science
68 * Carnegie Mellon University
69 * Pittsburgh PA 15213-3890
71 * any improvements or extensions that they make and grant Carnegie Mellon
72 * the rights to redistribute these changes.
75 #include <sys/cdefs.h>
76 __KERNEL_RCSID(0, "$NetBSD: mem.c,v 1.20 2009/05/08 09:33:58 skrll Exp $");
78 #include <sys/param.h>
79 #include <sys/systm.h>
82 #include <sys/malloc.h>
85 #include <sys/types.h>
86 #include <sys/device.h>
87 #include <sys/errno.h>
88 #include <sys/ioctl.h>
91 #include <sys/mutex.h>
95 #include <machine/iomod.h>
96 #include <machine/autoconf.h>
97 #include <machine/pmap.h>
99 #include <hp700/hp700/machdep.h>
100 #include <hp700/dev/cpudevs.h>
101 #include <hp700/dev/viper.h>
103 /* registers on the PCXL2 MIOC */
105 uint32_t pad
[0x20]; /* 0x000 */
106 uint32_t mioc_control
; /* 0x080 MIOC control bits */
107 uint32_t mioc_status
; /* 0x084 MIOC status bits */
108 uint32_t pad1
[6]; /* 0x088 */
109 uint32_t sltcv
; /* 0x0a0 L2 cache control */
110 #define SLTCV_AVWL 0x00002000 /* extra cycle for addr valid write low */
111 #define SLTCV_UP4COUT 0x00001000 /* update cache on CPU castouts */
112 #define SLTCV_EDCEN 0x08000000 /* enable error correction */
113 #define SLTCV_EDTAG 0x10000000 /* enable diagtag */
114 #define SLTCV_CHKTP 0x20000000 /* enable parity checking */
115 #define SLTCV_LOWPWR 0x40000000 /* low power mode */
116 #define SLTCV_ENABLE 0x80000000 /* enable L2 cache */
117 #define SLTCV_BITS "\020\15avwl\16up4cout\24edcen\25edtag\26chktp\27lowpwr\30l2ena"
118 uint32_t tagmask
; /* 0x0a4 L2 cache tag mask */
119 uint32_t diagtag
; /* 0x0a8 L2 invalidates tag */
120 uint32_t sltestat
; /* 0x0ac L2 last logged tag read */
121 uint32_t slteadd
; /* 0x0b0 L2 pa of -- " -- */
122 uint32_t pad2
[3]; /* 0x0b4 */
123 uint32_t mtcv
; /* 0x0c0 MIOC timings */
124 uint32_t ref
; /* 0x0cc MIOC refresh timings */
125 uint32_t pad3
[4]; /* 0x0d0 */
126 uint32_t mderradd
; /* 0x0e0 addr of most evil mem error */
127 uint32_t pad4
; /* 0x0e4 */
128 uint32_t dmaerr
; /* 0x0e8 addr of most evil dma error */
129 uint32_t dioerr
; /* 0x0ec addr of most evil dio error */
130 uint32_t gsc_timeout
; /* 0x0f0 1-compl of GSC timeout delay */
131 uint32_t hidmamem
; /* 0x0f4 amount of phys mem installed */
132 uint32_t pad5
[2]; /* 0x0f8 */
133 uint32_t memcomp
[16]; /* 0x100 memory address comparators */
134 uint32_t memmask
[16]; /* 0x140 masks for -- " -- */
135 uint32_t memtest
; /* 0x180 test address decoding */
136 uint32_t pad6
[0xf]; /* 0x184 */
137 uint32_t outchk
; /* 0x1c0 address decoding output */
138 uint32_t pad7
[0x168]; /* 0x200 */
139 uint32_t gsc15x_config
; /* 0x7a0 writev enable */
145 volatile struct vi_trs
*sc_vp
;
146 volatile struct l2_mioc
*sc_l2
;
149 int memmatch(device_t
, cfdata_t
, void *);
150 void memattach(device_t
, device_t
, void *);
152 CFATTACH_DECL_NEW(mem
, sizeof(struct mem_softc
), memmatch
, memattach
,
155 extern struct cfdriver mem_cd
;
158 dev_type_ioctl(mmioctl
);
159 dev_type_mmap(mmmmap
);
161 const struct cdevsw mem_cdevsw
= {
162 nullopen
, nullclose
, mmrw
, mmrw
, mmioctl
,
163 nostop
, notty
, nopoll
, mmmmap
,
166 static void *zeropage
;
168 /* A lock for the vmmap. */
172 memmatch(device_t parent
, cfdata_t cf
, void *aux
)
174 struct confargs
*ca
= aux
;
176 if (ca
->ca_type
.iodc_type
!= HPPA_TYPE_MEMORY
||
177 ca
->ca_type
.iodc_sv_model
!= HPPA_MEMORY_PDEP
)
183 memattach(device_t parent
, device_t self
, void *aux
)
185 struct pdc_iodc_minit pdc_minit PDC_ALIGNMENT
;
186 struct confargs
*ca
= aux
;
187 struct mem_softc
*sc
= device_private(self
);
188 int err
, pagezero_cookie
;
195 pagezero_cookie
= hp700_pagezero_map();
197 /* XXX check if we are dealing w/ Viper */
198 if (ca
->ca_hpa
== (hppa_hpa_t
)VIPER_HPA
) {
200 sc
->sc_vp
= (struct vi_trs
*)
201 &((struct iomod
*)ca
->ca_hpa
)->priv_trs
;
203 /* XXX other values seem to blow it up */
204 if (sc
->sc_vp
->vi_status
.hw_rev
== 0) {
209 case HPPA_BOARD_HP715_33
:
210 case HPPA_BOARD_HP715S_33
:
211 case HPPA_BOARD_HP715T_33
:
212 case HPPA_BOARD_HP715_50
:
213 case HPPA_BOARD_HP715S_50
:
214 case HPPA_BOARD_HP715T_50
:
215 case HPPA_BOARD_HP715_75
:
216 case HPPA_BOARD_HP725_50
:
217 case HPPA_BOARD_HP725_75
:
224 if (device_cfdata(self
)->cf_flags
& 1)
225 settimeout
= !settimeout
;
227 snprintb(bits
, sizeof(bits
), VIPER_BITS
, VI_CTRL
);
228 aprint_normal(" viper rev %x, ctrl %s",
229 sc
->sc_vp
->vi_status
.hw_rev
, bits
);
233 ((struct vi_ctrl
*)&vic
)->core_den
= 0;
234 ((struct vi_ctrl
*)&vic
)->sgc0_den
= 0;
235 ((struct vi_ctrl
*)&vic
)->sgc1_den
= 0;
236 ((struct vi_ctrl
*)&vic
)->eisa_den
= 1;
237 ((struct vi_ctrl
*)&vic
)->core_prf
= 1;
239 if (settimeout
&& ((struct vi_ctrl
*)&vic
)->vsc_tout
== 0)
240 ((struct vi_ctrl
*)&vic
)->vsc_tout
= 850; /* clks */
242 sc
->sc_vp
->vi_control
= vic
;
244 __asm
__volatile("stwas %1, 0(%0)"
245 :: "r" (&VI_CTRL
), "r" (vic
) : "memory");
248 snprintb(bits
, sizeof(bits
), VIPER_BITS
, VI_CTRL
);
249 printf (" >> %s", bits
);
256 if ((err
= pdc_call((iodcio_t
)pdc
, 0, PDC_IODC
, PDC_IODC_NINIT
,
257 &pdc_minit
, ca
->ca_hpa
, PAGE0
->imm_spa_size
)) < 0)
258 pdc_minit
.max_spa
= PAGE0
->imm_max_mem
;
260 hp700_pagezero_unmap(pagezero_cookie
);
262 aprint_normal(" size %d", pdc_minit
.max_spa
/ (1024*1024));
263 if (pdc_minit
.max_spa
% (1024*1024))
264 aprint_normal(".%d", pdc_minit
.max_spa
% (1024*1024));
267 /* L2 cache controller is a part of the memory controller on PCXL2 */
268 if (hppa_cpu_info
->hci_cputype
== hpcxl2
) {
269 sc
->sc_l2
= (struct l2_mioc
*)ca
->ca_hpa
;
271 snprintb(bits
, sizeof(bits
), SLTCV_BITS
, sc
->sc_l2
->sltcv
);
272 printf(", sltcv %s", bits
);
274 /* sc->sc_l2->sltcv |= SLTCV_UP4COUT; */
275 if (sc
->sc_l2
->sltcv
& SLTCV_ENABLE
) {
276 uint32_t tagmask
= sc
->sc_l2
->tagmask
>> 20;
277 aprint_normal(", %dMB L2 cache", tagmask
+ 1);
284 viper_setintrwnd(uint32_t mask
)
286 struct mem_softc
*sc
;
288 sc
= device_lookup_private(&mem_cd
,0);
291 sc
->sc_vp
->vi_intrwd
;
297 struct mem_softc
*sc
;
299 sc
= device_lookup_private(&mem_cd
, 0);
306 pagezero_cookie
= hp700_pagezero_map();
309 ((struct vi_ctrl
*)&vic
)->eisa_den
= 0;
310 sc
->sc_vp
->vi_control
= vic
;
311 __asm
__volatile("stwas %1, 0(%0)"
312 :: "r" (&VI_CTRL
), "r" (vic
) : "memory");
314 hp700_pagezero_unmap(pagezero_cookie
);
319 mmrw(dev_t dev
, struct uio
*uio
, int flags
)
327 while (uio
->uio_resid
> 0 && error
== 0) {
329 if (iov
->iov_len
== 0) {
332 if (uio
->uio_iovcnt
< 0)
336 switch (minor(dev
)) {
338 case DEV_MEM
: /* /dev/mem */
340 /* If the address isn't in RAM, bail. */
342 if (atop(v
) > physmem
) {
344 /* this will break us out of the loop */
348 c
= ptoa(physmem
) - v
;
349 c
= min(c
, uio
->uio_resid
);
350 error
= uiomove((char *)v
, c
, uio
);
353 case DEV_KMEM
: /* /dev/kmem */
356 c
= min(uio
->uio_resid
, (int)(PAGE_SIZE
- o
));
357 rw
= (uio
->uio_rw
== UIO_READ
) ? B_READ
: B_WRITE
;
358 if (atop(v
) > physmem
&& !uvm_kernacc((void *)v
, c
, rw
)) {
360 /* this will break us out of the loop */
363 error
= uiomove((void *)v
, c
, uio
);
366 case DEV_NULL
: /* /dev/null */
367 if (uio
->uio_rw
== UIO_WRITE
)
371 case DEV_ZERO
: /* /dev/zero */
372 /* Write to /dev/zero is ignored. */
373 if (uio
->uio_rw
== UIO_WRITE
) {
378 * On the first call, allocate and zero a page
379 * of memory for use with /dev/zero.
381 if (zeropage
== NULL
) {
383 malloc(PAGE_SIZE
, M_TEMP
, M_WAITOK
);
384 memset(zeropage
, 0, PAGE_SIZE
);
386 c
= min(iov
->iov_len
, PAGE_SIZE
);
387 error
= uiomove(zeropage
, c
, uio
);
398 mmmmap(dev_t dev
, off_t off
, int prot
)
405 * Allow access only in RAM.
408 if (off
< ptoa(firstusablepage
) ||
409 off
>= ptoa(lastusablepage
+ 1))