| @@ -1,198 +1,200 @@ | | | @@ -1,198 +1,200 @@ |
1 | /* $NetBSD: nvram.c,v 1.19 2011/06/05 06:33:43 tsutsui Exp $ */ | | 1 | /* $NetBSD: nvram.c,v 1.20 2015/03/06 12:41:05 christos Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1995 Leo Weppelman. | | 4 | * Copyright (c) 1995 Leo Weppelman. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * | | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 17 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 18 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 19 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 20 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 21 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 22 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 23 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 25 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | | 26 | */ |
27 | | | 27 | |
28 | /* | | 28 | /* |
29 | * Nvram driver | | 29 | * Nvram driver |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | #include <sys/cdefs.h> | | 32 | #include <sys/cdefs.h> |
33 | __KERNEL_RCSID(0, "$NetBSD: nvram.c,v 1.19 2011/06/05 06:33:43 tsutsui Exp $"); | | 33 | __KERNEL_RCSID(0, "$NetBSD: nvram.c,v 1.20 2015/03/06 12:41:05 christos Exp $"); |
34 | | | 34 | |
35 | #include <sys/param.h> | | 35 | #include <sys/param.h> |
36 | #include <sys/conf.h> | | 36 | #include <sys/conf.h> |
37 | #include <sys/kernel.h> | | 37 | #include <sys/kernel.h> |
38 | #include <sys/proc.h> | | 38 | #include <sys/proc.h> |
39 | #include <sys/systm.h> | | 39 | #include <sys/systm.h> |
40 | #include <sys/device.h> | | 40 | #include <sys/device.h> |
41 | #include <sys/buf.h> | | 41 | #include <sys/buf.h> |
42 | #include <sys/uio.h> | | 42 | #include <sys/uio.h> |
43 | | | 43 | |
44 | #include <machine/iomap.h> | | 44 | #include <machine/iomap.h> |
45 | #include <machine/cpu.h> | | 45 | #include <machine/cpu.h> |
46 | | | 46 | |
47 | #include <atari/dev/clockreg.h> | | 47 | #include <atari/dev/clockreg.h> |
48 | #include <atari/dev/nvramvar.h> | | 48 | #include <atari/dev/nvramvar.h> |
49 | | | 49 | |
50 | #include "ioconf.h" | | 50 | #include "ioconf.h" |
51 | | | 51 | |
52 | #include "nvr.h" | | 52 | #include "nvr.h" |
53 | | | 53 | |
| | | 54 | #ifdef NVRAM_DEBUG |
| | | 55 | #define DPRINTF(a) printf a |
| | | 56 | #else |
| | | 57 | #define DPRINTF(a) |
| | | 58 | #endif |
| | | 59 | |
54 | #define MC_NVRAM_CSUM (MC_NVRAM_START + MC_NVRAM_SIZE - 2) | | 60 | #define MC_NVRAM_CSUM (MC_NVRAM_START + MC_NVRAM_SIZE - 2) |
55 | | | 61 | |
56 | #if NNVR > 0 | | 62 | #if NNVR > 0 |
57 | static void nvram_set_csum(u_char csum); | | 63 | static void nvram_set_csum(u_char csum); |
58 | static int nvram_csum_valid(u_char csum); | | 64 | static int nvram_csum_valid(u_char csum); |
59 | static u_char nvram_csum(void); | | 65 | static u_char nvram_csum(void); |
60 | | | 66 | |
61 | /* | | 67 | /* |
62 | * Auto config stuff.... | | 68 | * Auto config stuff.... |
63 | */ | | 69 | */ |
64 | static void nvr_attach(device_t, device_t, void *); | | 70 | static void nvr_attach(device_t, device_t, void *); |
65 | static int nvr_match(device_t, cfdata_t, void *); | | 71 | static int nvr_match(device_t, cfdata_t, void *); |
66 | | | 72 | |
67 | CFATTACH_DECL_NEW(nvr, sizeof(struct nvr_softc), | | 73 | CFATTACH_DECL_NEW(nvr, sizeof(struct nvr_softc), |
68 | nvr_match, nvr_attach, NULL, NULL); | | 74 | nvr_match, nvr_attach, NULL, NULL); |
69 | | | 75 | |
70 | /*ARGSUSED*/ | | 76 | /*ARGSUSED*/ |
71 | static int | | 77 | static int |
72 | nvr_match(device_t parent, cfdata_t cf, void *aux) | | 78 | nvr_match(device_t parent, cfdata_t cf, void *aux) |
73 | { | | 79 | { |
74 | if (!strcmp((char *)aux, "nvr")) | | 80 | if (!strcmp((char *)aux, "nvr")) |
75 | return (1); | | 81 | return (1); |
76 | return (0); | | 82 | return (0); |
77 | } | | 83 | } |
78 | | | 84 | |
79 | /*ARGSUSED*/ | | 85 | /*ARGSUSED*/ |
80 | static void | | 86 | static void |
81 | nvr_attach(device_t parent, device_t self, void *aux) | | 87 | nvr_attach(device_t parent, device_t self, void *aux) |
82 | { | | 88 | { |
83 | struct nvr_softc *sc; | | 89 | struct nvr_softc *sc; |
84 | int nreg; | | 90 | int nreg; |
85 | | | 91 | |
86 | /* | | 92 | /* |
87 | * Check the validity of the NVram contents | | 93 | * Check the validity of the NVram contents |
88 | */ | | 94 | */ |
89 | if (!nvram_csum_valid(nvram_csum())) { | | 95 | if (!nvram_csum_valid(nvram_csum())) { |
90 | printf(": Invalid checksum - re-initialized"); | | 96 | printf(": Invalid checksum - re-initialized"); |
91 | for (nreg = MC_NVRAM_START; nreg < MC_NVRAM_CSUM; nreg++) | | 97 | for (nreg = MC_NVRAM_START; nreg < MC_NVRAM_CSUM; nreg++) |
92 | mc146818_write(RTC, nreg, 0); | | 98 | mc146818_write(RTC, nreg, 0); |
93 | nvram_set_csum(nvram_csum()); | | 99 | nvram_set_csum(nvram_csum()); |
94 | } | | 100 | } |
95 | sc = device_private(self); | | 101 | sc = device_private(self); |
96 | sc->sc_dev = self; | | 102 | sc->sc_dev = self; |
97 | sc->sc_flags = NVR_CONFIGURED; | | 103 | sc->sc_flags = NVR_CONFIGURED; |
98 | printf("\n"); | | 104 | printf("\n"); |
99 | } | | 105 | } |
100 | /* | | 106 | /* |
101 | * End of auto config stuff.... | | 107 | * End of auto config stuff.... |
102 | */ | | 108 | */ |
103 | #endif /* NNVR > 0 */ | | 109 | #endif /* NNVR > 0 */ |
104 | | | 110 | |
105 | /* | | 111 | /* |
106 | * Kernel internal interface | | 112 | * Kernel internal interface |
107 | */ | | 113 | */ |
108 | int | | 114 | int |
109 | nvr_get_byte(int byteno) | | 115 | nvr_get_byte(int byteno) |
110 | { | | 116 | { |
111 | #if NNVR > 0 | | 117 | #if NNVR > 0 |
112 | struct nvr_softc *sc; | | 118 | struct nvr_softc *sc; |
113 | | | 119 | |
114 | sc = device_lookup_private(&nvr_cd, 0); | | 120 | sc = device_lookup_private(&nvr_cd, 0); |
115 | if (!(sc->sc_flags & NVR_CONFIGURED)) | | 121 | if (!(sc->sc_flags & NVR_CONFIGURED)) |
116 | return(NVR_INVALID); | | 122 | return(NVR_INVALID); |
117 | return (mc146818_read(RTC, byteno + MC_NVRAM_START) & 0xff); | | 123 | return (mc146818_read(RTC, byteno + MC_NVRAM_START) & 0xff); |
118 | #else | | 124 | #else |
119 | return(NVR_INVALID); | | 125 | return(NVR_INVALID); |
120 | #endif /* NNVR > 0 */ | | 126 | #endif /* NNVR > 0 */ |
121 | } | | 127 | } |
122 | | | 128 | |
123 | #if NNVR > 0 | | 129 | #if NNVR > 0 |
124 | | | 130 | |
125 | int | | 131 | int |
126 | nvram_uio(struct uio *uio) | | 132 | nvram_uio(struct uio *uio) |
127 | { | | 133 | { |
128 | int i; | | 134 | int i; |
129 | off_t offset; | | 135 | off_t offset; |
130 | int nleft; | | 136 | int nleft; |
131 | u_char buf[MC_NVRAM_CSUM - MC_NVRAM_START + 1]; | | 137 | u_char buf[MC_NVRAM_CSUM - MC_NVRAM_START + 1]; |
132 | u_char *p; | | 138 | u_char *p; |
133 | struct nvr_softc *sc; | | 139 | struct nvr_softc *sc; |
134 | | | 140 | |
135 | sc = device_lookup_private(&nvr_cd,0); | | 141 | sc = device_lookup_private(&nvr_cd,0); |
136 | if (!(sc->sc_flags & NVR_CONFIGURED)) | | 142 | if (!(sc->sc_flags & NVR_CONFIGURED)) |
137 | return ENXIO; | | 143 | return ENXIO; |
138 | | | 144 | |
139 | #ifdef NV_DEBUG | | 145 | DPRINTF(("Request to transfer %d bytes offset: %d, %s nvram\n", |
140 | printf("Request to transfer %d bytes offset: %d, %s nvram\n", | | | |
141 | (long)uio->uio_resid, (long)uio->uio_offset, | | 146 | (long)uio->uio_resid, (long)uio->uio_offset, |
142 | (uio->uio_rw == UIO_READ) ? "from" : "to"); | | 147 | (uio->uio_rw == UIO_READ) ? "from" : "to")); |
143 | #endif /* NV_DEBUG */ | | | |
144 | | | 148 | |
145 | offset = uio->uio_offset + MC_NVRAM_START; | | 149 | offset = uio->uio_offset + MC_NVRAM_START; |
146 | nleft = uio->uio_resid; | | 150 | nleft = uio->uio_resid; |
147 | if (offset + nleft >= MC_NVRAM_CSUM) { | | 151 | if (offset + nleft >= MC_NVRAM_CSUM) { |
148 | if (offset == MC_NVRAM_CSUM) | | 152 | if (offset == MC_NVRAM_CSUM) |
149 | return (0); | | 153 | return (0); |
150 | nleft = MC_NVRAM_CSUM - offset; | | 154 | nleft = MC_NVRAM_CSUM - offset; |
151 | if (nleft <= 0) | | 155 | if (nleft <= 0) |
152 | return (EINVAL); | | 156 | return (EINVAL); |
153 | } | | 157 | } |
154 | #ifdef NV_DEBUG | | 158 | DPRINTF(("Translated: offset = %d, bytes: %d\n", (long)offset, nleft)); |
155 | printf("Translated: offset = %d, bytes: %d\n", (long)offset, nleft); | | | |
156 | #endif /* NV_DEBUG */ | | | |
157 | | | 159 | |
158 | if (uio->uio_rw == UIO_READ) { | | 160 | if (uio->uio_rw == UIO_READ) { |
159 | for (i = 0, p = buf; i < nleft; i++, p++) | | 161 | for (i = 0, p = buf; i < nleft; i++, p++) |
160 | *p = mc146818_read(RTC, offset + i); | | 162 | *p = mc146818_read(RTC, offset + i); |
161 | } | | 163 | } |
162 | if ((i = uiomove(buf, nleft, uio)) != 0) | | 164 | if ((i = uiomove(buf, nleft, uio)) != 0) |
163 | return (i); | | 165 | return (i); |
164 | if (uio->uio_rw == UIO_WRITE) { | | 166 | if (uio->uio_rw == UIO_WRITE) { |
165 | for (i = 0, p = buf; i < nleft; i++, p++) | | 167 | for (i = 0, p = buf; i < nleft; i++, p++) |
166 | mc146818_write(RTC, offset + i, *p); | | 168 | mc146818_write(RTC, offset + i, *p); |
167 | nvram_set_csum(nvram_csum()); | | 169 | nvram_set_csum(nvram_csum()); |
168 | } | | 170 | } |
169 | return(0); | | 171 | return(0); |
170 | } | | 172 | } |
171 | | | 173 | |
172 | static u_char | | 174 | static u_char |
173 | nvram_csum(void) | | 175 | nvram_csum(void) |
174 | { | | 176 | { |
175 | u_char csum; | | 177 | u_char csum; |
176 | int nreg; | | 178 | int nreg; |
177 | | | 179 | |
178 | for (csum = 0, nreg = MC_NVRAM_START; nreg < MC_NVRAM_CSUM; nreg++) | | 180 | for (csum = 0, nreg = MC_NVRAM_START; nreg < MC_NVRAM_CSUM; nreg++) |
179 | csum += mc146818_read(RTC, nreg); | | 181 | csum += mc146818_read(RTC, nreg); |
180 | return(csum); | | 182 | return(csum); |
181 | } | | 183 | } |
182 | | | 184 | |
183 | static int | | 185 | static int |
184 | nvram_csum_valid(u_char csum) | | 186 | nvram_csum_valid(u_char csum) |
185 | { | | 187 | { |
186 | if (((~csum & 0xff) != mc146818_read(RTC, MC_NVRAM_CSUM)) | | 188 | if (((~csum & 0xff) != mc146818_read(RTC, MC_NVRAM_CSUM)) |
187 | || (csum != mc146818_read(RTC, MC_NVRAM_CSUM + 1))) | | 189 | || (csum != mc146818_read(RTC, MC_NVRAM_CSUM + 1))) |
188 | return 0; | | 190 | return 0; |
189 | return 1; | | 191 | return 1; |
190 | } | | 192 | } |
191 | | | 193 | |
192 | static void | | 194 | static void |
193 | nvram_set_csum(u_char csum) | | 195 | nvram_set_csum(u_char csum) |
194 | { | | 196 | { |
195 | mc146818_write(RTC, MC_NVRAM_CSUM, ~csum); | | 197 | mc146818_write(RTC, MC_NVRAM_CSUM, ~csum); |
196 | mc146818_write(RTC, MC_NVRAM_CSUM + 1, csum); | | 198 | mc146818_write(RTC, MC_NVRAM_CSUM + 1, csum); |
197 | } | | 199 | } |
198 | #endif /* NNVR > 0 */ | | 200 | #endif /* NNVR > 0 */ |