1*a6ce3504Sthorpej /* $NetBSD: cmos.c,v 1.14 2023/12/20 15:00:07 thorpej Exp $ */
256db7325Sdyoung
356db7325Sdyoung /*
456db7325Sdyoung * Copyright (C) 2003 JONE System Co., Inc.
556db7325Sdyoung * All right reserved.
656db7325Sdyoung *
756db7325Sdyoung * Copyright (C) 1999, 2000, 2001, 2002 JEPRO Co., Ltd.
856db7325Sdyoung * All right reserved.
956db7325Sdyoung *
1056db7325Sdyoung * Redistribution and use in source and binary forms, with or without
1156db7325Sdyoung * modification, are permitted provided that the following conditions
1256db7325Sdyoung * are met:
1356db7325Sdyoung *
1456db7325Sdyoung * 1. Redistributions of source code must retain the above copyright
1556db7325Sdyoung * notice, this list of conditions and the following disclaimer.
1656db7325Sdyoung * 2. Redistributions in binary form must reproduce the above copyright
1756db7325Sdyoung * notice, this list of conditions and the following disclaimer in the
1856db7325Sdyoung * documentation and/or other materials provided with the distribution.
1956db7325Sdyoung *
2056db7325Sdyoung * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2156db7325Sdyoung * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2256db7325Sdyoung * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2356db7325Sdyoung * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2456db7325Sdyoung * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2556db7325Sdyoung * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2656db7325Sdyoung * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2756db7325Sdyoung * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2856db7325Sdyoung * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2956db7325Sdyoung * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3056db7325Sdyoung * SUCH DAMAGE.
3156db7325Sdyoung *
3256db7325Sdyoung */
3356db7325Sdyoung /*
3456db7325Sdyoung * Copyright (c) 2007 David Young. All right reserved.
3556db7325Sdyoung *
3656db7325Sdyoung * Redistribution and use in source and binary forms, with or
3756db7325Sdyoung * without modification, are permitted provided that the following
3856db7325Sdyoung * conditions are met:
3956db7325Sdyoung *
4056db7325Sdyoung * 1. Redistributions of source code must retain the above copyright
4156db7325Sdyoung * notice, this list of conditions and the following disclaimer.
4256db7325Sdyoung * 2. Redistributions in binary form must reproduce the above
4356db7325Sdyoung * copyright notice, this list of conditions and the following
4456db7325Sdyoung * disclaimer in the documentation and/or other materials provided
4556db7325Sdyoung * with the distribution.
4656db7325Sdyoung *
4756db7325Sdyoung * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
4856db7325Sdyoung * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
4956db7325Sdyoung * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
5056db7325Sdyoung * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
5156db7325Sdyoung * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5256db7325Sdyoung * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
5356db7325Sdyoung * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
5456db7325Sdyoung * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
5556db7325Sdyoung * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
5656db7325Sdyoung * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
5756db7325Sdyoung * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5856db7325Sdyoung * SUCH DAMAGE.
5956db7325Sdyoung */
60ceed9c72Slukem
61ceed9c72Slukem #include <sys/cdefs.h>
62*a6ce3504Sthorpej __KERNEL_RCSID(0, "$NetBSD: cmos.c,v 1.14 2023/12/20 15:00:07 thorpej Exp $");
63ceed9c72Slukem
6456db7325Sdyoung #include <sys/param.h>
6556db7325Sdyoung #include <sys/systm.h>
6656db7325Sdyoung #include <sys/kernel.h>
6756db7325Sdyoung #include <sys/ioctl.h>
6856db7325Sdyoung #include <sys/proc.h>
6956db7325Sdyoung #include <sys/device.h>
7056db7325Sdyoung #include <sys/conf.h>
7156db7325Sdyoung #include <sys/kauth.h>
7256db7325Sdyoung
7359e0aa24Sdyoung #include <sys/bus.h>
7456db7325Sdyoung #include <machine/intr.h>
7556db7325Sdyoung
7656db7325Sdyoung #include <dev/isa/isareg.h>
7756db7325Sdyoung #include <dev/isa/isavar.h>
7856db7325Sdyoung #include <dev/ic/mc146818reg.h>
7956db7325Sdyoung #include <i386/isa/nvram.h>
8056db7325Sdyoung
81e7ae23fdSchristos #include "ioconf.h"
82e7ae23fdSchristos
8356db7325Sdyoung #define CMOS_SUM 32
8456db7325Sdyoung #define CMOS_BIOSSPEC 34 /* start of BIOS-specific configuration data */
8556db7325Sdyoung
8656db7325Sdyoung #define NVRAM_SUM (MC_NVRAM_START + CMOS_SUM)
8756db7325Sdyoung #define NVRAM_BIOSSPEC (MC_NVRAM_START + CMOS_BIOSSPEC)
8856db7325Sdyoung
8956db7325Sdyoung #define CMOS_SIZE NVRAM_BIOSSPEC
9056db7325Sdyoung
9156db7325Sdyoung dev_type_open(cmos_open);
9256db7325Sdyoung dev_type_read(cmos_read);
9356db7325Sdyoung dev_type_write(cmos_write);
9456db7325Sdyoung
9556db7325Sdyoung static void cmos_sum(uint8_t *, int, int, int);
9656db7325Sdyoung
9756db7325Sdyoung const struct cdevsw cmos_cdevsw = {
98a68f9396Sdholland .d_open = cmos_open,
99a68f9396Sdholland .d_close = nullclose,
100a68f9396Sdholland .d_read = cmos_read,
101a68f9396Sdholland .d_write = cmos_write,
102a68f9396Sdholland .d_ioctl = noioctl,
103a68f9396Sdholland .d_stop = nostop,
104a68f9396Sdholland .d_tty = notty,
105a68f9396Sdholland .d_poll = nopoll,
106a68f9396Sdholland .d_mmap = nommap,
107a68f9396Sdholland .d_kqfilter = nokqfilter,
108f9228f42Sdholland .d_discard = nodiscard,
109a68f9396Sdholland .d_flag = D_OTHER | D_MPSAFE
11056db7325Sdyoung };
11156db7325Sdyoung
112698b4a3bSad static kmutex_t cmos_lock;
1130a11462fSad static uint8_t cmos_buf[CMOS_SIZE];
114698b4a3bSad
11556db7325Sdyoung void
cmosattach(int n)11656db7325Sdyoung cmosattach(int n)
11756db7325Sdyoung {
118a122ceefSad
119698b4a3bSad mutex_init(&cmos_lock, MUTEX_DEFAULT, IPL_NONE);
12056db7325Sdyoung }
12156db7325Sdyoung
12256db7325Sdyoung int
cmos_open(dev_t dev,int flags,int ifmt,struct lwp * l)12356db7325Sdyoung cmos_open(dev_t dev, int flags, int ifmt, struct lwp *l)
12456db7325Sdyoung {
12556db7325Sdyoung
126e6e18939Schristos return kauth_authorize_machdep(l->l_cred,
1272d1c9683Selad KAUTH_MACHDEP_NVRAM, NULL, NULL, NULL, NULL);
12856db7325Sdyoung }
12956db7325Sdyoung
13056db7325Sdyoung static void
cmos_fetch(void)1310a11462fSad cmos_fetch(void)
13256db7325Sdyoung {
13356db7325Sdyoung int i, s;
13456db7325Sdyoung uint8_t *p;
13556db7325Sdyoung
1360a11462fSad p = cmos_buf;
13756db7325Sdyoung s = splclock();
13856db7325Sdyoung for (i = 0; i < CMOS_SIZE; i++)
1390a11462fSad *p++ = mc146818_read(NULL, i);
14056db7325Sdyoung splx(s);
14156db7325Sdyoung }
14256db7325Sdyoung
14356db7325Sdyoung int
cmos_read(dev_t dev,struct uio * uio,int ioflag)14456db7325Sdyoung cmos_read(dev_t dev, struct uio *uio, int ioflag)
14556db7325Sdyoung {
146698b4a3bSad int error;
14756db7325Sdyoung
148698b4a3bSad if (uio->uio_offset + uio->uio_resid > CMOS_SIZE)
14956db7325Sdyoung return EINVAL;
15056db7325Sdyoung
151698b4a3bSad mutex_enter(&cmos_lock);
1520a11462fSad cmos_fetch();
1530a11462fSad error = uiomove(cmos_buf + uio->uio_offset, uio->uio_resid, uio);
154698b4a3bSad mutex_exit(&cmos_lock);
15556db7325Sdyoung
156698b4a3bSad return error;
15756db7325Sdyoung }
15856db7325Sdyoung
15956db7325Sdyoung int
cmos_write(dev_t dev,struct uio * uio,int ioflag)16056db7325Sdyoung cmos_write(dev_t dev, struct uio *uio, int ioflag)
16156db7325Sdyoung {
16256db7325Sdyoung int error = 0, i, s;
16356db7325Sdyoung
164698b4a3bSad if (uio->uio_offset + uio->uio_resid > CMOS_SIZE)
165698b4a3bSad return EINVAL;
166698b4a3bSad
167698b4a3bSad mutex_enter(&cmos_lock);
1680a11462fSad cmos_fetch();
1690a11462fSad error = uiomove(cmos_buf + uio->uio_offset, uio->uio_resid, uio);
170698b4a3bSad if (error == 0) {
1710a11462fSad cmos_sum(cmos_buf, NVRAM_DISKETTE, NVRAM_SUM, NVRAM_SUM);
17256db7325Sdyoung s = splclock();
17356db7325Sdyoung for (i = NVRAM_DISKETTE; i < CMOS_SIZE; i++)
1740a11462fSad mc146818_write(NULL, i, cmos_buf[i]);
17556db7325Sdyoung splx(s);
176698b4a3bSad }
177698b4a3bSad mutex_exit(&cmos_lock);
17856db7325Sdyoung
17956db7325Sdyoung return error;
18056db7325Sdyoung }
18156db7325Sdyoung
18256db7325Sdyoung static void
cmos_sum(uint8_t * p,int from,int to,int offset)18356db7325Sdyoung cmos_sum(uint8_t *p, int from, int to, int offset)
18456db7325Sdyoung {
18556db7325Sdyoung int i;
18656db7325Sdyoung uint16_t sum;
18756db7325Sdyoung
18856db7325Sdyoung #ifdef CMOS_DEBUG
18956db7325Sdyoung printf("%s: from %d to %d and store %d\n", __func__, from, to, offset);
19056db7325Sdyoung #endif
19156db7325Sdyoung
19256db7325Sdyoung sum = 0;
19356db7325Sdyoung for (i = from; i < to; i++)
19456db7325Sdyoung sum += p[i];
19556db7325Sdyoung p[offset] = sum >> 8;
19656db7325Sdyoung p[offset + 1] = sum & 0xff;
19756db7325Sdyoung }
198