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