Add cmos(4) for reading/writing CMOS RAM on x86 boxes. This driver

comes from Takahiro Kambe, with some mods by me.
This commit is contained in:
dyoung 2007-02-06 07:28:59 +00:00
parent 9e85b986d1
commit 56db732551
5 changed files with 340 additions and 4 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: mi,v 1.971 2007/01/30 19:40:09 elad Exp $
# $NetBSD: mi,v 1.972 2007/02/06 07:28:59 dyoung Exp $
./etc/mtree/set.man man-sys-root
./usr/share/info/am-utils.info man-amd-info info
./usr/share/info/as.info man-computil-info bfd,info
@ -925,6 +925,7 @@
./usr/share/man/cat4/i386/apm.0 man-sys-catman .cat
./usr/share/man/cat4/i386/autoconf.0 man-sys-catman .cat
./usr/share/man/cat4/i386/busmouse.0 man-obsolete obsolete
./usr/share/man/cat4/i386/cmos.0 man-sys-catman .cat
./usr/share/man/cat4/i386/com.0 man-obsolete obsolete
./usr/share/man/cat4/i386/cons.0 man-sys-catman .cat
./usr/share/man/cat4/i386/console.0 man-sys-catman .cat
@ -3338,6 +3339,7 @@
./usr/share/man/man4/i386/apm.4 man-sys-man .man
./usr/share/man/man4/i386/autoconf.4 man-sys-man .man
./usr/share/man/man4/i386/busmouse.4 man-obsolete obsolete
./usr/share/man/man4/i386/cmos.4 man-sys-man .man
./usr/share/man/man4/i386/com.4 man-obsolete obsolete
./usr/share/man/man4/i386/cons.4 man-sys-man .man
./usr/share/man/man4/i386/console.4 man-sys-man .man

View File

@ -1,7 +1,9 @@
# $NetBSD: Makefile,v 1.64 2006/06/24 12:22:52 kardel Exp $
# $NetBSD: Makefile,v 1.65 2007/02/06 07:29:00 dyoung Exp $
# from: @(#)Makefile 8.1 (Berkeley) 6/5/93
MAN= apm.4 autoconf.4 console.4 elansc.4 fdc.4 \
MAN= apm.4 autoconf.4 \
cmos.4 console.4 \
elansc.4 fdc.4 \
geodewdog.4 geodecntr.4 gscpcib.4 \
intro.4 io.4 lms.4 lpt.4 mem.4 mms.4 npx.4 ndis.4 \
pcibios.4 pnpbios.4 sony.4 spic.4 vald.4 \

View File

@ -0,0 +1,76 @@
.\" The following commands are required for all man pages.
.Dd February 5, 2007
.Os
.Dt cmos 4 i386
.Sh NAME
.Nm cmos
.Nd Read/write access to IBM PC/AT CMOS RAM
.Sh SYNOPSIS
.Cd pseudo-device cmos
.Sh DESCRIPTION
Use
.Nm
to read the real-time clock and ISA configuration data from an
ISA-compatible CMOS RAM, and to write the ISA configuration data.
.Pp
A program reads between 0 and 48 bytes from the CMOS RAM, starting at
byte 0 of the RAM, using a single call to
.Xr read 2 .
Likewise, a program writes between 0 and 48 bytes to the CMOS RAM,
starting at byte 0 of the RAM, using a single call to
.Xr write 2 .
.Pp
.Nm
does not allow programs to overwrite the real-time clock data
(bytes 0 through 9), the status registers (10 through 13),
the diagnostic status or CMOS shutdown status (bytes 14 and 15),
or the CMOS checksum (bytes 46 and 47).
Writes to those bytes are ignored.
.Pp
On writes,
.Nm
recomputes the CMOS checksum and writes it to the CMOS RAM.
.Sh EXAMPLES
Display entire contents of CMOS RAM:
.Bd -literal -offset indent
# dd if=/dev/cmos bs=48 count=1 | od -t x1
0000000 37 00 09 00 22 00 06 13 04 80 26 02 50 80 00 00
0000020 00 51 f0 00 01 80 02 00 fc 0f 2f 00 00 00 00 00
0000040 00 80 81 f0 ff 00 00 00 00 00 00 00 00 00 05 ee
0000060
.Ed
.Pp
Change boot order on Soekris net4521 to PXE ROM, Primary HDD,
Secondary HDD:
.Bd -literal -offset indent
# dd if=/dev/cmos of=/tmp/cmos0 bs=48 count=1
1+0 records in
1+0 records out
48 bytes transferred in 0.001 secs (48000 bytes/sec)
# cp /tmp/cmos0 /tmp/cmos
# printf '\exf0\ex80\ex81\exff' | dd bs=1 seek=33 conv=notrunc of=/tmp/cmos
4+0 records in
4+0 records out
4 bytes transferred in 0.001 secs (4000 bytes/sec)
# dd if=/tmp/cmos of=/dev/cmos
0+1 records in
0+1 records out
48 bytes transferred in 0.001 secs (48000 bytes/sec)
.Ed
.Sh ERRORS
A program can read or write no more than 48 bytes to
.Nm .
.Xr read 2 /
.Xr write 2
will return
.Er EINVAL
if more than 48 bytes are read / written at once.
.Sh AUTHORS
The original
.Nm
driver was written by
.An Takahiro Kambe Aq taca@back-street.net .
.An David Young Aq dyoung@NetBSD.org
modified the original and added it to
.Nx .
.\" .Sh BUGS

View File

@ -1,4 +1,4 @@
# $NetBSD: files.i386,v 1.299 2007/01/06 18:42:36 jmcneill Exp $
# $NetBSD: files.i386,v 1.300 2007/02/06 07:29:00 dyoung Exp $
#
# new style config file for i386 architecture
#
@ -327,6 +327,12 @@ include "dev/vme/files.vme"
#
include "dev/gpib/files.gpib"
#
# CMOS RAM
#
defpseudo cmos
file arch/i386/isa/cmos.c cmos needs-flag
#
# Other mainbus-attached devices
#

250
sys/arch/i386/isa/cmos.c Normal file
View File

@ -0,0 +1,250 @@
/* $Id: cmos.c,v 1.1 2007/02/06 07:29:00 dyoung Exp $ */
/*
* Copyright (C) 2003 JONE System Co., Inc.
* All right reserved.
*
* Copyright (C) 1999, 2000, 2001, 2002 JEPRO Co., Ltd.
* All right reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of JEPRO Co., Ltd. nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
/*
* Copyright (c) 2007 David Young. All right reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* 3. The name of David Young may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/ioctl.h>
#include <sys/proc.h>
#include <sys/device.h>
#include <sys/conf.h>
#include <sys/kauth.h>
#include <machine/bus.h>
#include <machine/intr.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
#include <dev/ic/mc146818reg.h>
#include <i386/isa/nvram.h>
#define CMOS_SUM 32
#define CMOS_BIOSSPEC 34 /* start of BIOS-specific configuration data */
#define NVRAM_SUM (MC_NVRAM_START + CMOS_SUM)
#define NVRAM_BIOSSPEC (MC_NVRAM_START + CMOS_BIOSSPEC)
#define CMOS_SIZE NVRAM_BIOSSPEC
struct cmos_softc { /* driver status information */
int sc_open;
uint8_t sc_buf[CMOS_SIZE];
} cmos_softc;
#ifdef CMOS_DEBUG
int cmos_debug = 0;
#endif
void cmosattach(int);
dev_type_open(cmos_open);
dev_type_close(cmos_close);
dev_type_read(cmos_read);
dev_type_write(cmos_write);
static void cmos_sum(uint8_t *, int, int, int);
#ifdef CMOS_DEBUG
static void cmos_dump(uint8_t *);
#endif
const struct cdevsw cmos_cdevsw = {
.d_open = cmos_open, .d_close = cmos_close, .d_read = cmos_read,
.d_write = cmos_write, .d_ioctl = noioctl,
.d_stop = nostop, .d_tty = notty, .d_poll = nopoll, .d_mmap = nommap,
.d_kqfilter = nokqfilter,
};
void
cmosattach(int n)
{
printf("cmos: attached.\n");
}
int
cmos_open(dev_t dev, int flags, int ifmt, struct lwp *l)
{
struct cmos_softc *sc = &cmos_softc;
struct proc *p = l->l_proc;
int error;
error = kauth_authorize_generic(p->p_cred, KAUTH_GENERIC_ISSUSER,
&p->p_acflag);
if (error != 0)
return error;
sc->sc_open = 1;
#ifdef CMOS_DEBUG
printf("cmos: opened\n");
#endif
return 0;
}
int
cmos_close(dev_t dev, int flags, int ifmt, struct lwp *l)
{
struct cmos_softc *sc = &cmos_softc;
sc->sc_open = 0;
#ifdef CMOS_DEBUG
printf("cmos: closed\n");
#endif
return 0;
}
static void
cmos_fetch(struct cmos_softc *sc)
{
int i, s;
uint8_t *p;
p = sc->sc_buf;
s = splclock();
for (i = 0; i < CMOS_SIZE; i++)
*p++ = mc146818_read(sc, i);
splx(s);
}
int
cmos_read(dev_t dev, struct uio *uio, int ioflag)
{
struct cmos_softc *sc = &cmos_softc;
if (uio->uio_resid > CMOS_SIZE)
return EINVAL;
#ifdef CMOS_DEBUG
printf("cmos: try to read to %d\n", CMOS_SIZE);
#endif
cmos_fetch(sc);
return uiomove(sc->sc_buf, CMOS_SIZE, uio);
}
int
cmos_write(dev_t dev, struct uio *uio, int ioflag)
{
struct cmos_softc *sc = &cmos_softc;
int error = 0, i, s;
cmos_fetch(sc);
error = uiomove(sc->sc_buf, CMOS_SIZE, uio);
#ifdef CMOS_DEBUG
printf("write %d\n", l);
if (cmos_debug)
cmos_dump(sc->sc_buf);
#endif
if (error)
return error;
cmos_sum(sc->sc_buf, NVRAM_DISKETTE, NVRAM_SUM, NVRAM_SUM);
#ifdef CMOS_DEBUG
if (cmos_debug)
cmos_dump(sc->sc_buf);
#endif
s = splclock();
for (i = NVRAM_DISKETTE; i < CMOS_SIZE; i++)
mc146818_write(sc, i, sc->sc_buf[i]);
splx(s);
return error;
}
static void
cmos_sum(uint8_t *p, int from, int to, int offset)
{
int i;
uint16_t sum;
#ifdef CMOS_DEBUG
printf("%s: from %d to %d and store %d\n", __func__, from, to, offset);
#endif
sum = 0;
for (i = from; i < to; i++)
sum += p[i];
p[offset] = sum >> 8;
p[offset + 1] = sum & 0xff;
}
#ifdef CMOS_DEBUG
static void
cmos_dump(uint8_t *p)
{
int i;
for (i = 0; i < CMOS_SIZE; i++) {
if (i % 16 == 0)
printf("%02x:", i);
printf(" %02x", p[i]);
if (i % 16 == 15)
printf("\n", buf);
}
printf("\n");
}
#endif