1/*	$NetBSD: nvram.c,v 1.19 2014/03/16 05:20:25 dholland Exp $	*/
2
3/*-
4 * Copyright (C) 1998	Internet Research Institute, Inc.
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
18 *	Internet Research Institute, Inc.
19 * 4. The name of the author may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#include <sys/cdefs.h>
35__KERNEL_RCSID(0, "$NetBSD: nvram.c,v 1.19 2014/03/16 05:20:25 dholland Exp $");
36
37#include <sys/types.h>
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/conf.h>
41#include <sys/kernel.h>
42#include <sys/device.h>
43#include <sys/malloc.h>
44#include <sys/event.h>
45
46#include <machine/autoconf.h>
47#include <machine/pio.h>
48
49#define NVRAM_NONE  0
50#define NVRAM_IOMEM 1
51#define NVRAM_PORT  2
52
53#define NVRAM_SIZE 0x2000
54
55static void nvram_attach(device_t, device_t, void *);
56static int nvram_match(device_t, cfdata_t, void *);
57
58struct nvram_softc {
59	int nv_type;
60	char *nv_port;
61	char *nv_data;
62};
63
64CFATTACH_DECL_NEW(nvram, sizeof(struct nvram_softc),
65    nvram_match, nvram_attach, NULL, NULL);
66
67extern struct cfdriver nvram_cd;
68
69dev_type_read(nvramread);
70dev_type_write(nvramwrite);
71dev_type_mmap(nvrammmap);
72
73const struct cdevsw nvram_cdevsw = {
74	.d_open = nullopen,
75	.d_close = nullclose,
76	.d_read = nvramread,
77	.d_write = nvramwrite,
78	.d_ioctl = noioctl,
79	.d_stop = nostop,
80	.d_tty = notty,
81	.d_poll = nopoll,
82	.d_mmap = nvrammmap,
83	.d_kqfilter = nokqfilter,
84	.d_discard = nodiscard,
85	.d_flag = 0
86};
87
88int
89nvram_match(device_t parent, cfdata_t cf, void *aux)
90{
91	struct confargs *ca = aux;
92
93	if (strcmp(ca->ca_name, "nvram") != 0)
94		return 0;
95
96	if (ca->ca_nreg == 0)
97		return 0;
98
99	return 1;
100}
101
102void
103nvram_attach(device_t parent, device_t self, void *aux)
104{
105	struct nvram_softc *sc = device_private(self);
106	struct confargs *ca = aux;
107	int *reg = ca->ca_reg;
108
109	printf("\n");
110
111	switch (ca->ca_nreg) {
112
113	case 8:						/* untested */
114		sc->nv_type = NVRAM_IOMEM;
115		sc->nv_data = mapiodev(ca->ca_baseaddr + reg[0], reg[1], false);
116		break;
117
118	case 16:
119		sc->nv_type = NVRAM_PORT;
120		sc->nv_port = mapiodev(ca->ca_baseaddr + reg[0], reg[1], false);
121		sc->nv_data = mapiodev(ca->ca_baseaddr + reg[2], reg[3], false);
122		break;
123
124	case 0:
125	default:
126		sc->nv_type = NVRAM_NONE;
127		return;
128	}
129}
130
131int
132nvramread(dev_t dev, struct uio *uio, int flag)
133{
134	struct nvram_softc *sc;
135	u_int off, cnt;
136	int i;
137	int error = 0;
138	char *buf;
139
140	sc = device_lookup_private(&nvram_cd, 0);
141
142	off = uio->uio_offset;
143	cnt = uio->uio_resid;
144
145	if (off > NVRAM_SIZE || cnt > NVRAM_SIZE)
146		return EFAULT;
147
148	if (off + cnt > NVRAM_SIZE)
149		cnt = NVRAM_SIZE - off;
150
151	buf = malloc(NVRAM_SIZE, M_DEVBUF, M_WAITOK);
152	if (buf == NULL) {
153		error = EAGAIN;
154		goto out;
155	}
156
157	switch (sc->nv_type) {
158
159	case NVRAM_IOMEM:
160		for (i = 0; i < NVRAM_SIZE; i++)
161			buf[i] = sc->nv_data[i * 16];
162
163		break;
164
165	case NVRAM_PORT:
166		for (i = 0; i < NVRAM_SIZE; i += 32) {
167			int j;
168
169			out8(sc->nv_port, i / 32);
170			for (j = 0; j < 32; j++) {
171				buf[i + j] = sc->nv_data[j * 16];
172			}
173		}
174		break;
175
176	default:
177		goto out;
178	}
179
180	error = uiomove(buf + off, cnt, uio);
181
182out:
183	if (buf)
184		free(buf, M_DEVBUF);
185
186	return error;
187}
188
189int
190nvramwrite(dev_t dev, struct uio *uio, int flag)
191{
192	return ENXIO;
193}
194
195paddr_t
196nvrammmap(dev_t dev, off_t off, int prot)
197{
198	return -1;
199}
200