Applied, thanks! Zhaoming Luo, le mer. 11 déc. 2024 08:54:15 +0800, a ecrit: > A /hurd/rtc translator will be created as, users can create a /dev/rtc > device using the following command: > ``` > sudo settrans -c /dev/rtc /hurd/rtc > ``` > > * Makefile: add rtc-cmos server into the compile chain > * hurd/pioctl.defs: new file. Interfaces for rtc ioctl operations > * hurd/rtc.h: new file. Interfaces for rtc device > * rtc/Makefile: new file. Makefile for rtc server > * rtc/main.c: new file. Initialisation for rtc translator > * rtc/mig-mutate.h: new file. Type translation for rtc server > * rtc/rtc-cmos_pioctl-ops.c: new file. The rtc-cmos server-side implementation > > Signed-off-by: Zhaoming Luo <zhming...@163.com> > --- > Makefile | 3 +- > hurd/pioctl.defs | 59 ++++++++ > hurd/rtc.h | 51 +++++++ > rtc/Makefile | 39 ++++++ > rtc/main.c | 104 ++++++++++++++ > rtc/mig-mutate.h | 24 ++++ > rtc/rtc-cmos_pioctl-ops.c | 276 ++++++++++++++++++++++++++++++++++++++ > 7 files changed, 555 insertions(+), 1 deletion(-) > create mode 100644 hurd/pioctl.defs > create mode 100644 hurd/rtc.h > create mode 100644 rtc/Makefile > create mode 100644 rtc/main.c > create mode 100644 rtc/mig-mutate.h > create mode 100644 rtc/rtc-cmos_pioctl-ops.c > > diff --git a/Makefile b/Makefile > index 4d848221..9d9e33c3 100644 > --- a/Makefile > +++ b/Makefile > @@ -47,7 +47,8 @@ prog-subdirs = auth proc exec term \ > init \ > devnode \ > eth-multiplexer \ > - shutdown > + shutdown \ > + rtc > > ifeq ($(HAVE_LIBRUMP),yes) > prog-subdirs += rumpdisk > diff --git a/hurd/pioctl.defs b/hurd/pioctl.defs > new file mode 100644 > index 00000000..77d830e7 > --- /dev/null > +++ b/hurd/pioctl.defs > @@ -0,0 +1,59 @@ > +/* Definitions for /dev/rtc ioctls > + > + Copyright (C) 2024 Free Software Foundation, Inc. > + > + This file is part of the GNU Hurd. > + > + The GNU Hurd is free software; you can redistribute it and/or > + modify it under the terms of the GNU General Public License as > + published by the Free Software Foundation; either version 2, or (at > + your option) any later version. > + > + The GNU Hurd is distributed in the hope that it will be useful, but > + WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program; if not, write to the Free Software > + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ > + > +/* Ioctl group 'p'; the subsystem is derived from calculations in > + hurd/ioctls.defs. */ > +subsystem pioctl 140000; > + > +#include <hurd/ioctl_types.defs> > + > +import <hurd/rtc.h>; > + > +#ifdef PIOCTL_IMPORTS > +PIOCTL_IMPORTS > +#endif > + > +INTR_INTERFACE > + > +/* This is the arg for a struct rtc_time as specified by the > + definition of _IOT_rtc_time in $(hurd)/hurd/rtc.h. */ > +type rtc_time_t = struct[9] of int; > + > +skip; skip; skip; /* 0 1 2 */ > + > +/* 3 RTC_UIE_ON */ > +routine pioctl_rtc_uie_on ( > + reqport: io_t); > + > +/* 4 RTC_UIE_OFF */ > +routine pioctl_rtc_uie_off ( > + reqport: io_t); > + > +skip; skip; skip; skip; /* 5 6 7 8 */ > + > +/* 9 RTC_RD_TIME */ > +routine pioctl_rtc_rd_time ( > + reqport: io_t; > + out tm: rtc_time_t); > + > +/* 10 RTC_SET_TIME */ > +routine pioctl_rtc_set_time ( > + reqport: io_t; > + tm: rtc_time_t); > diff --git a/hurd/rtc.h b/hurd/rtc.h > new file mode 100644 > index 00000000..58bf5536 > --- /dev/null > +++ b/hurd/rtc.h > @@ -0,0 +1,51 @@ > +/* GNU Hurd RTC interface > + > + Copyright (C) 2024 Free Software Foundation, Inc. > + > + This file is part of the GNU Hurd. > + > + The GNU Hurd is free software; you can redistribute it and/or > + modify it under the terms of the GNU General Public License as > + published by the Free Software Foundation; either version 2, or (at > + your option) any later version. > + > + The GNU Hurd is distributed in the hope that it will be useful, but > + WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program; if not, write to the Free Software > + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ > + > +#ifndef _RTC_H > +#define _RTC_H 1 > + > +#include <hurd/ioctl.h> > + > +struct rtc_time > +{ > + int tm_sec; > + int tm_min; > + int tm_hour; > + int tm_mday; > + int tm_mon; > + int tm_year; > + int tm_wday; > + int tm_yday; > + int tm_isdst; > +}; > +typedef struct rtc_time rtc_time_t; > + > +#define _IOT_rtc_time _IOT(_IOTS(int),9,0,0,0,0) > + > +/* ioctl calls that are permitted to the /dev/rtc interface, if > + any of the RTC drivers are enabled. */ > + > +#define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on. */ > +#define RTC_UIE_OFF _IO('p', 0x04) /* ... off. */ > + > +#define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time) /* Read RTC time. */ > +#define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time) /* Set RTC time. */ > + > +#endif /* rtc.h */ > diff --git a/rtc/Makefile b/rtc/Makefile > new file mode 100644 > index 00000000..ce32de4c > --- /dev/null > +++ b/rtc/Makefile > @@ -0,0 +1,39 @@ > +# Makefile for rtc server > +# > +# Copyright (C) 2024 Free Software Foundation, Inc. > +# > +# This file is part of the GNU Hurd. > +# > +# The GNU Hurd is free software; you can redistribute it and/or > +# modify it under the terms of the GNU General Public License as > +# published by the Free Software Foundation; either version 2, or (at > +# your option) any later version. > +# > +# The GNU Hurd is distributed in the hope that it will be useful, but > +# WITHOUT ANY WARRANTY; without even the implied warranty of > +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > +# General Public License for more details. > +# > +# You should have received a copy of the GNU General Public License > +# along with this program; if not, write to the Free Software > +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ > + > +dir := rtc > +makemode := server > + > +SRCS = main.c rtc-cmos_pioctl-ops.c > +MIGSRCS = pioctlServer.c > + > +OBJS = main.o pioctlServer.o rtc-cmos_pioctl-ops.o > + > +HURDLIBS = trivfs shouldbeinlibc ports > + > +target = rtc > + > +include ../Makeconf > + > +MIGCOMSFLAGS += -prefix rtc_ > +mig-sheader-prefix = rtc_ > +pioctl-MIGSFLAGS = -imacros $(srcdir)/mig-mutate.h > + > +rtc_pioctl_S.h pioctlServer.c: mig-mutate.h > diff --git a/rtc/main.c b/rtc/main.c > new file mode 100644 > index 00000000..19bf73b9 > --- /dev/null > +++ b/rtc/main.c > @@ -0,0 +1,104 @@ > +/* A translator for accessing rtc > + > + Copyright (C) 2024 Free Software Foundation, Inc. > + > + This file is part of the GNU Hurd. > + > + The GNU Hurd is free software; you can redistribute it and/or > + modify it under the terms of the GNU General Public License as > + published by the Free Software Foundation; either version 2, or (at > + your option) any later version. > + > + The GNU Hurd is distributed in the hope that it will be useful, but > + WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program; if not, write to the Free Software > + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ > + > +#include <version.h> > + > +#include <error.h> > +#include <stdbool.h> > +#include <argp.h> > +#include <hurd/trivfs.h> > +#include <hurd/ports.h> > +#include <hurd/rtc.h> > +#include <sys/io.h> > + > +#include "rtc_pioctl_S.h" > + > +const char *argp_program_version = STANDARD_HURD_VERSION (rtc); > + > +static struct trivfs_control *rtccntl; > + > +int trivfs_fstype = FSTYPE_DEV; > +int trivfs_fsid = 0; > +int trivfs_support_read = 1; > +int trivfs_support_write = 0; > +int trivfs_support_exec = 0; > +int trivfs_allow_open = O_READ | O_WRITE; > + > +static const struct argp rtc_argp = > +{ NULL, NULL, NULL, "Real-Time Clock device" }; > + > +static int > +demuxer (mach_msg_header_t *inp, mach_msg_header_t *outp) > +{ > + mig_routine_t routine; > + if ((routine = rtc_pioctl_server_routine (inp)) || > + (routine = NULL, trivfs_demuxer (inp, outp))) > + { > + if (routine) > + (*routine) (inp, outp); > + return TRUE; > + } > + else > + return FALSE; > +} > + > +int > +main (int argc, char **argv) > +{ > + error_t err; > + mach_port_t bootstrap; > + > + argp_parse (&rtc_argp, argc, argv, 0, 0, 0); > + > + task_get_bootstrap_port (mach_task_self (), &bootstrap); > + if (bootstrap == MACH_PORT_NULL) > + error (1, 0, "Must be started as a translator"); > + > + /* Request for permission to do i/o on port numbers 0x70 and 0x71 for > + accessing RTC registers. Do this before replying to our parent, so > + we don't end up saying "I'm ready!" and then immediately exit with > + an error. */ > + err = ioperm (0x70, 2, true); > + if (err) > + error (1, err, "Request IO permission failed"); > + > + /* Reply to our parent. */ > + err = trivfs_startup (bootstrap, O_NORW, NULL, NULL, NULL, NULL, &rtccntl); > + mach_port_deallocate (mach_task_self (), bootstrap); > + if (err) > + error (1, err, "trivfs_startup failed"); > + > + /* Launch. */ > + ports_manage_port_operations_one_thread (rtccntl->pi.bucket, demuxer, > + 2 * 60 * 1000); > + > + return 0; > +} > + > +void > +trivfs_modify_stat (struct trivfs_protid *cred, struct stat *st) > +{ > +} > + > +error_t > +trivfs_goaway (struct trivfs_control *fsys, int flags) > +{ > + exit (EXIT_SUCCESS); > +} > diff --git a/rtc/mig-mutate.h b/rtc/mig-mutate.h > new file mode 100644 > index 00000000..ddead5be > --- /dev/null > +++ b/rtc/mig-mutate.h > @@ -0,0 +1,24 @@ > +/* Type translation for rtc operations > + > + Copyright (C) 2024 Free Software Foundation, Inc. > + > + This file is part of the GNU Hurd. > + > + The GNU Hurd is free software; you can redistribute it and/or > + modify it under the terms of the GNU General Public License as > + published by the Free Software Foundation; either version 2, or (at > + your option) any later version. > + > + The GNU Hurd is distributed in the hope that it will be useful, but > + WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program; if not, write to the Free Software > + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ > + > +#define IO_INTRAN trivfs_protid_t trivfs_begin_using_protid (io_t) > +#define IO_INTRAN_PAYLOAD trivfs_protid_t trivfs_begin_using_protid_payload > +#define IO_DESTRUCTOR trivfs_end_using_protid (trivfs_protid_t) > +#define PIOCTL_IMPORTS import "../libtrivfs/mig-decls.h"; > diff --git a/rtc/rtc-cmos_pioctl-ops.c b/rtc/rtc-cmos_pioctl-ops.c > new file mode 100644 > index 00000000..8657cce1 > --- /dev/null > +++ b/rtc/rtc-cmos_pioctl-ops.c > @@ -0,0 +1,276 @@ > +/* Server side implementation for rtc-cmos > + > + Copyright (C) 2024 Free Software Foundation, Inc. > + > + This file is part of the GNU Hurd. > + > + The GNU Hurd is free software; you can redistribute it and/or > + modify it under the terms of the GNU General Public License as > + published by the Free Software Foundation; either version 2, or (at > + your option) any later version. > + > + The GNU Hurd is distributed in the hope that it will be useful, but > + WITHOUT ANY WARRANTY; without even the implied warranty of > + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > + General Public License for more details. > + > + You should have received a copy of the GNU General Public License > + along with this program; if not, write to the Free Software > + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ > + > +/* This implementation is largely based on sys-utils/hwclock-cmos.c from > + util-linux. */ > + > +/* A struct tm has int fields (it is defined in POSIX) > + tm_sec 0-59, 60 or 61 only for leap seconds > + tm_min 0-59 > + tm_hour 0-23 > + tm_mday 1-31 > + tm_mon 0-11 > + tm_year number of years since 1900 > + tm_wday 0-6, 0=Sunday > + tm_yday 0-365 > + tm_isdst >0: yes, 0: no, <0: unknown */ > + > +#include "rtc_pioctl_S.h" > +#include <hurd/rtc.h> > +#include <hurd/hurd_types.h> > +#include <sys/io.h> > +#include <stdbool.h> > + > +/* Conversions to and from RTC internal format. */ > +#define BCD_TO_BIN(val) ((val)=((val)&15) + (((val)>>4)&15)*10 + \ > + ((val)>>8)*100) > +#define BIN_TO_BCD(val) ((val)=(((val)/100)<<8) + \ > + ((((val)/10)%10)<<4) + (val)%10) > + > +/* POSIX uses 1900 as epoch for a struct tm, and 1970 for a time_t. */ > +#define TM_EPOCH 1900 > + > +#define CLOCK_CTL_ADDR 0x70 > +#define CLOCK_DATA_ADDR 0x71 > + > +#define is_leap(year) \ > + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) > + > +static const int mon_yday[2][13] = > +{ > + /* Normal years. */ > + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, > + /* Leap years. */ > + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } > +}; > + > + > +static inline unsigned char > +cmos_read (unsigned char reg) > +{ > + outb_p (reg, CLOCK_CTL_ADDR); > + return inb_p (CLOCK_DATA_ADDR); > +} > + > +static inline void > +cmos_write (unsigned char reg, unsigned char val) > +{ > + outb_p (reg, CLOCK_CTL_ADDR); > + outb_p (val, CLOCK_DATA_ADDR); > +} > + > +static inline int > +cmos_clock_busy (void) > +{ > + /* Poll bit 7 (UIP) of Control Register A. */ > + return (cmos_read (10) & 0x80); > +} > + > +/* Calculate day of year based on month, day of month, and year. The value > + it returns is in binary format. */ > +static int > +calculate_yday (const struct rtc_time *tm) > +{ > + return mon_yday[is_leap (tm->tm_year)][tm->tm_mon] + tm->tm_mday - 1; > +} > + > +/* 3 RTC_UIE_ON -- Enable update-ended interrupt. */ > +kern_return_t > +rtc_S_pioctl_rtc_uie_on (struct trivfs_protid *cred) > +{ > + return EOPNOTSUPP; > +} > + > +/* 4 RTC_UIE_OFF -- Disable update-ended interrupt. */ > +kern_return_t > +rtc_S_pioctl_rtc_uie_off (struct trivfs_protid *cred) > +{ > + return EOPNOTSUPP; > +} > + > +/* 9 RTC_RD_TIME -- Read RTC time. */ > +kern_return_t > +rtc_S_pioctl_rtc_rd_time (struct trivfs_protid *cred, struct rtc_time *tm) > +{ > + unsigned char status = 0; > + unsigned char pmbit = 0; > + int time_passed_in_milliseconds = 0; > + bool read_rtc_successfully = false; > + > + if (!cred) > + return EOPNOTSUPP; > + if (!(cred->po->openmodes & O_READ)) > + return EBADF; > + > + /* When we wait for 100 ms (it takes too long), we exit with error. */ > + while (time_passed_in_milliseconds < 100) > + { > + if (!cmos_clock_busy ()) > + { > + tm->tm_sec = cmos_read (0); > + tm->tm_min = cmos_read (2); > + tm->tm_hour = cmos_read (4); > + tm->tm_wday = cmos_read (6); > + tm->tm_mday = cmos_read (7); > + tm->tm_mon = cmos_read (8); > + tm->tm_year = cmos_read (9); > + status = cmos_read (11); > + /* Unless the clock changed while we were reading, consider this > + a good clock read. */ > + if (tm->tm_sec == cmos_read (0)) > + { > + read_rtc_successfully = true; > + break; > + } > + } > + usleep (1000); > + time_passed_in_milliseconds++; > + } > + > + if (!read_rtc_successfully) > + return EBUSY; > + > + /* If the data we just read is in BCD format, convert it to binary > + format. */ > + if (!(status & 0x04)) > + { > + BCD_TO_BIN (tm->tm_sec); > + BCD_TO_BIN (tm->tm_min); > + pmbit = (tm->tm_hour & 0x80); > + tm->tm_hour &= 0x7f; > + BCD_TO_BIN (tm->tm_hour); > + BCD_TO_BIN (tm->tm_wday); > + BCD_TO_BIN (tm->tm_mday); > + BCD_TO_BIN (tm->tm_mon); > + BCD_TO_BIN (tm->tm_year); > + } > + > + /* We don't use the century byte of the Hardware Clock since we > + don't know its address (usually 50 or 55). Here, we follow the > + advice of the X/Open Base Working Group: "if century is not > + specified, then values in the range [69-99] refer to years in the > + twentieth century (1969 to 1999 inclusive), and values in the > + range [00-68] refer to years in the twenty-first century (2000 to > + 2068 inclusive)". */ > + tm->tm_wday -= 1; > + tm->tm_mon -= 1; > + if (tm->tm_year < 69) > + tm->tm_year += 100; > + > + /* Calculate day of year. */ > + tm->tm_yday = calculate_yday (tm); > + > + if (pmbit) > + { > + tm->tm_hour += 12; > + if (tm->tm_hour == 24) > + tm->tm_hour = 0; > + } > + > + /* We don't know whether it's daylight. */ > + tm->tm_isdst = -1; > + > + return KERN_SUCCESS; > +} > + > +/* 10 RTC_SET_TIME -- Set RTC time. */ > +kern_return_t > +rtc_S_pioctl_rtc_set_time (struct trivfs_protid *cred, struct rtc_time tm) > +{ > + unsigned char save_control, save_freq_select, pmbit = 0; > + > + if (!cred) > + return EOPNOTSUPP; > + if (!(cred->po->openmodes & O_WRITE)) > + return EBADF; > + > + /* CMOS byte 10 (clock status register A) has 3 bitfields: > + bit 7: 1 if data invalid, update in progress (read-only bit) > + (this is raised 224 us before the actual update starts) > + 6-4 select base frequency > + 010: 32768 Hz time base (default) > + 111: reset > + all other combinations are manufacturer-dependent > + (e.g.: DS1287: 010 = start oscillator, anything else = stop) > + 3-0 rate selection bits for interrupt > + 0000 none (may stop RTC) > + 0001, 0010 give same frequency as 1000, 1001 > + 0011 122 microseconds (minimum, 8192 Hz) > + .... each increase by 1 halves the frequency, doubles the period > + 1111 500 milliseconds (maximum, 2 Hz) > + 0110 976.562 microseconds (default 1024 Hz). */ > + > + /* Tell the clock it's being set. */ > + save_control = cmos_read (11); > + cmos_write (11, (save_control | 0x80)); > + /* Stop and reset prescaler. */ > + save_freq_select = cmos_read (10); > + cmos_write (10, (save_freq_select | 0x70)); > + > + tm.tm_year %= 100; > + tm.tm_mon += 1; > + tm.tm_wday += 1; > + > + /* 12hr mode; the default is 24hr mode. */ > + if (!(save_control & 0x02)) > + { > + if (tm.tm_hour == 0) > + tm.tm_hour = 24; > + if (tm.tm_hour > 12) > + { > + tm.tm_hour -= 12; > + pmbit = 0x80; > + } > + } > + > + /* BCD mode - the default. */ > + if (!(save_control & 0x04)) > + { > + BIN_TO_BCD (tm.tm_sec); > + BIN_TO_BCD (tm.tm_min); > + BIN_TO_BCD (tm.tm_hour); > + BIN_TO_BCD (tm.tm_wday); > + BIN_TO_BCD (tm.tm_mday); > + BIN_TO_BCD (tm.tm_mon); > + BIN_TO_BCD (tm.tm_year); > + } > + > + cmos_write (0, tm.tm_sec); > + cmos_write (2, tm.tm_min); > + cmos_write (4, tm.tm_hour | pmbit); > + cmos_write (6, tm.tm_wday); > + cmos_write (7, tm.tm_mday); > + cmos_write (8, tm.tm_mon); > + cmos_write (9, tm.tm_year); > + > + /* The kernel sources, linux/arch/i386/kernel/time.c, have the > + following comment: > + > + The following flags have to be released exactly in this order, > + otherwise the DS12887 (popular MC146818A clone with integrated > + battery and quartz) will not reset the oscillator and will not > + update precisely 500 ms later. You won't find this mentioned in > + the Dallas Semiconductor data sheets, but who believes data > + sheets anyway ... -- Markus Kuhn. */ > + cmos_write (11, save_control); > + cmos_write (10, save_freq_select); > + > + return KERN_SUCCESS; > +} > -- > 2.45.2 >
-- Samuel > Voici mon problème, j'ai deux PCs relies par des cartes ethernet, > configures avec le protocole PPP. -+- Romain in Guide du linuxien pervers - "Ils sont fous ces romains !" -+-