xref: /netbsd-src/sys/arch/i386/isa/cmos.c (revision a6ce3504542ed8b086b0b8c7681fff4540e0cdd8)
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