PIT Time make clean!
This commit is contained in:
parent
0a428c6cad
commit
21b15dcffe
2
Makefile
2
Makefile
|
@ -119,7 +119,7 @@ KernObj=$(patsubst %.c,$(KOBJDIR)/%.o,$(KernSources))
|
||||||
KernDep=$(patsubst %.c,$(KOBJDIR)/%.d,$(KernSources))
|
KernDep=$(patsubst %.c,$(KOBJDIR)/%.d,$(KernSources))
|
||||||
|
|
||||||
all :
|
all :
|
||||||
make OS/K -j 8
|
@make OS/K -j 8
|
||||||
|
|
||||||
## MISC MAKEFILE ------------------------------------------------------------- #
|
## MISC MAKEFILE ------------------------------------------------------------- #
|
||||||
|
|
||||||
|
|
157
ProjectTree
157
ProjectTree
|
@ -1,157 +0,0 @@
|
||||||
#=----------------------------------------------------------------------------=#
|
|
||||||
# GNU GPL OS/K #
|
|
||||||
# #
|
|
||||||
# Desc: #
|
|
||||||
# #
|
|
||||||
# #
|
|
||||||
# Copyright © 2018-2019 The OS/K Team #
|
|
||||||
# #
|
|
||||||
# This file is part of OS/K. #
|
|
||||||
# #
|
|
||||||
# OS/K 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 3 of the License, or #
|
|
||||||
# any later version. #
|
|
||||||
# #
|
|
||||||
# OS/K 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 OS/K. If not, see <https://www.gnu.org/licenses/>. #
|
|
||||||
#=----------------------------------------------------------------------------=#
|
|
||||||
|
|
||||||
|
|
||||||
.
|
|
||||||
├── boot
|
|
||||||
│ ├── grub
|
|
||||||
│ │ ├── grub.cfg
|
|
||||||
│ │ └── multiboot.pdf
|
|
||||||
│ ├── loader
|
|
||||||
│ │ ├── cpu
|
|
||||||
│ │ │ ├── cpu32.inc
|
|
||||||
│ │ │ └── cpu.inc
|
|
||||||
│ │ ├── io
|
|
||||||
│ │ │ └── terminal.inc
|
|
||||||
│ │ ├── mem
|
|
||||||
│ │ │ ├── management.inc
|
|
||||||
│ │ │ └── structures.inc
|
|
||||||
│ │ ├── multiboot
|
|
||||||
│ │ │ ├── check.inc
|
|
||||||
│ │ │ └── header.inc
|
|
||||||
│ │ └── loader.asm
|
|
||||||
│ └── folder.desc
|
|
||||||
├── build
|
|
||||||
│ ├── create_disk.sh
|
|
||||||
│ ├── install-os-k.sh
|
|
||||||
│ └── kernel.ld
|
|
||||||
├── include
|
|
||||||
│ ├── ex
|
|
||||||
│ │ ├── lock.h
|
|
||||||
│ │ └── malloc.h
|
|
||||||
│ ├── init
|
|
||||||
│ │ ├── boot.h
|
|
||||||
│ │ └── mboot.h
|
|
||||||
│ ├── io
|
|
||||||
│ │ ├── ata.h
|
|
||||||
│ │ ├── cursor.h
|
|
||||||
│ │ ├── keyb.h
|
|
||||||
│ │ ├── spkr.h
|
|
||||||
│ │ └── vga.h
|
|
||||||
│ ├── ke
|
|
||||||
│ │ ├── cpuid.h
|
|
||||||
│ │ ├── idt.h
|
|
||||||
│ │ ├── proc.h
|
|
||||||
│ │ ├── sched.h
|
|
||||||
│ │ ├── spinlock.h
|
|
||||||
│ │ └── time.h
|
|
||||||
│ ├── lib
|
|
||||||
│ │ ├── buf.h
|
|
||||||
│ │ └── list.h
|
|
||||||
│ ├── mm
|
|
||||||
│ │ ├── heap.h
|
|
||||||
│ │ ├── malloc.h
|
|
||||||
│ │ └── mm.h
|
|
||||||
│ ├── po
|
|
||||||
│ │ └── shtdwn.h
|
|
||||||
│ ├── sh
|
|
||||||
│ │ ├── argv.h
|
|
||||||
│ │ └── shell.h
|
|
||||||
│ ├── asm.h
|
|
||||||
│ ├── errno.h
|
|
||||||
│ ├── kernel.h
|
|
||||||
│ ├── libc.h
|
|
||||||
│ └── vers.h
|
|
||||||
├── kaleid
|
|
||||||
│ ├── kernel
|
|
||||||
│ │ ├── init
|
|
||||||
│ │ │ ├── info.c
|
|
||||||
│ │ │ ├── init.c
|
|
||||||
│ │ │ ├── ssp.c
|
|
||||||
│ │ │ └── table.c
|
|
||||||
│ │ ├── io
|
|
||||||
│ │ │ ├── ata.asm
|
|
||||||
│ │ │ ├── ata.c
|
|
||||||
│ │ │ ├── cursor.c
|
|
||||||
│ │ │ ├── keyb.c
|
|
||||||
│ │ │ ├── spkr.c
|
|
||||||
│ │ │ └── vga.c
|
|
||||||
│ │ ├── ke
|
|
||||||
│ │ │ ├── cpuf.asm
|
|
||||||
│ │ │ ├── cpuf.inc
|
|
||||||
│ │ │ ├── cpuid.c
|
|
||||||
│ │ │ ├── idt.c
|
|
||||||
│ │ │ ├── isr.asm
|
|
||||||
│ │ │ ├── log.c
|
|
||||||
│ │ │ ├── panic.c
|
|
||||||
│ │ │ ├── pit.c
|
|
||||||
│ │ │ └── rtc.c
|
|
||||||
│ │ ├── mm
|
|
||||||
│ │ │ ├── gdt.asm
|
|
||||||
│ │ │ ├── gdt.c
|
|
||||||
│ │ │ ├── heap.c
|
|
||||||
│ │ │ ├── malloc.c
|
|
||||||
│ │ │ ├── map.c
|
|
||||||
│ │ │ ├── paging.asm
|
|
||||||
│ │ │ └── paging.c
|
|
||||||
│ │ ├── po
|
|
||||||
│ │ │ └── shtdwn.c
|
|
||||||
│ │ ├── ps
|
|
||||||
│ │ │ └── sched.c
|
|
||||||
│ │ └── sh
|
|
||||||
│ │ ├── argv.c
|
|
||||||
│ │ ├── musage.c
|
|
||||||
│ │ ├── shcmds.c
|
|
||||||
│ │ ├── shell.c
|
|
||||||
│ │ └── shell.h
|
|
||||||
│ ├── libbuf
|
|
||||||
│ │ ├── bclose.c
|
|
||||||
│ │ ├── bflush.c
|
|
||||||
│ │ ├── bgetc.c
|
|
||||||
│ │ ├── bmisc.c
|
|
||||||
│ │ ├── bopen.c
|
|
||||||
│ │ ├── bprint.c
|
|
||||||
│ │ ├── bputc.c
|
|
||||||
│ │ ├── bread.c
|
|
||||||
│ │ ├── bscan.c
|
|
||||||
│ │ ├── bscroll.c
|
|
||||||
│ │ └── bwrite.c
|
|
||||||
│ └── libc
|
|
||||||
│ ├── atoi.c
|
|
||||||
│ ├── ctype.c
|
|
||||||
│ ├── errno.c
|
|
||||||
│ ├── itoa.c
|
|
||||||
│ ├── mem.c
|
|
||||||
│ ├── rand.c
|
|
||||||
│ ├── sprintf.c
|
|
||||||
│ ├── string.c
|
|
||||||
│ └── strtol.c
|
|
||||||
├── AUTHORS
|
|
||||||
├── ChangeLog
|
|
||||||
├── COPYING
|
|
||||||
├── Makefile
|
|
||||||
├── ProjectTree
|
|
||||||
└── README.md
|
|
||||||
|
|
||||||
28 directories, 101 files
|
|
|
@ -45,7 +45,7 @@ struct Time_t
|
||||||
|
|
||||||
struct TimerFilo_t {
|
struct TimerFilo_t {
|
||||||
uint countDown;
|
uint countDown;
|
||||||
ulong sema; // semaphore, don't know how it is for instance
|
ulong sema;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
void KeSetupRTC(void);
|
void KeSetupRTC(void);
|
||||||
|
@ -53,13 +53,15 @@ void KeEnableRTC(void);
|
||||||
|
|
||||||
ulong KeGetTimeStamp(void);
|
ulong KeGetTimeStamp(void);
|
||||||
ulong KeGetClockTicks(void);
|
ulong KeGetClockTicks(void);
|
||||||
|
Time_t *KeGetOriginTime(void);
|
||||||
void KeDelayExecution(uint);
|
void KeDelayExecution(uint);
|
||||||
|
|
||||||
Time_t *KeGetCurTime(void);
|
Time_t *KeGetCurTime(void);
|
||||||
char *KeFormatCurTime(void);
|
char *KeFormatCurTime(void);
|
||||||
|
void KeSetCurTime(Time_t);
|
||||||
|
|
||||||
void KeEnablePIT(void);
|
void KeEnablePIT(void);
|
||||||
void KeSleep(uint);
|
void KeSleep(uint);
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------//
|
//----------------------------------------------------------------------------//
|
||||||
|
|
|
@ -27,27 +27,26 @@
|
||||||
#include <ke/idt.h>
|
#include <ke/idt.h>
|
||||||
|
|
||||||
#define COUNTDONE 1
|
#define COUNTDONE 1
|
||||||
#define PIT_FREQUENCY 100 // Hz = 10ms
|
#define PIT_FREQUENCY 1000 // Hz = 10ms
|
||||||
|
|
||||||
static TimerFilo_t timerFilo[20]; //20 concurrent sleep max
|
static TimerFilo_t timerFilo[20]; //20 concurrent sleep max
|
||||||
static ulong Ticks = 0;
|
static ulong Ticks = 0;
|
||||||
|
static Time_t CurTime;
|
||||||
|
static char TimeFmtBuf[22] = { 0 };
|
||||||
|
|
||||||
//
|
//
|
||||||
// ISR handler for the Programmable Interval Timer
|
// ISR handler for the Programmable Interval Timer
|
||||||
//
|
//
|
||||||
static void HandlePIT(ISRFrame_t *regs)
|
static void HandlePIT(ISRFrame_t *regs)
|
||||||
{
|
{
|
||||||
|
Ticks++;
|
||||||
for (uchar i = 0; i < 20; i++) {
|
for (uchar i = 0; i < 20; i++) {
|
||||||
|
|
||||||
// debug
|
|
||||||
//DebugLog("Hello world of PIT ticks !\n");
|
|
||||||
//
|
|
||||||
|
|
||||||
if (timerFilo[i].countDown > 0) {
|
if (timerFilo[i].countDown > 0) {
|
||||||
timerFilo[i].countDown--;
|
timerFilo[i].countDown--;
|
||||||
|
|
||||||
if (timerFilo[i].countDown == 0)
|
if (timerFilo[i].countDown == 0)
|
||||||
i; //XXX SendMessage a message to timerFifo[i].sema that COUNTDONE;
|
timerFilo[i].sema = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeSendEOItoPIC(0x28);
|
KeSendEOItoPIC(0x28);
|
||||||
|
@ -72,15 +71,17 @@ void KeSleep(uint delay)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
timerBlock->countDown = delay;
|
timerBlock->countDown = delay;
|
||||||
// wait for a message on timerFifo[i].sema
|
|
||||||
}
|
|
||||||
|
|
||||||
|
while (!timerBlock->sema) {
|
||||||
|
KeDelayExecution(1);
|
||||||
|
}
|
||||||
|
timerBlock->sema = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void KeEnablePIT(void)
|
void KeEnablePIT(void)
|
||||||
{
|
{
|
||||||
ulong flags = KePauseIRQs();
|
ulong flags = KePauseIRQs();
|
||||||
char readIrqs;
|
uint divisor = 1193180 / PIT_FREQUENCY; // PIT base frequency / Needed frequency
|
||||||
uint divisor = 1193180 / PIT_FREQUENCY;
|
|
||||||
|
|
||||||
KeRegisterISR(HandlePIT, 0x20);
|
KeRegisterISR(HandlePIT, 0x20);
|
||||||
|
|
||||||
|
@ -92,8 +93,97 @@ void KeEnablePIT(void)
|
||||||
// Setting up the IRQs
|
// Setting up the IRQs
|
||||||
KeUnmaskIRQ(0);
|
KeUnmaskIRQ(0);
|
||||||
|
|
||||||
DebugLog("\tPIT activated with rate generator mode 10ms\n");
|
DebugLog("\tPIT activated with rate generator mode %d ms\n", 1000/PIT_FREQUENCY);
|
||||||
|
|
||||||
KeRestoreIRQs(flags);
|
KeRestoreIRQs(flags);
|
||||||
KeEnableNMI();
|
KeEnableNMI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char *KeFormatCurTime(void)
|
||||||
|
{
|
||||||
|
Time_t *RtcTime = KeGetCurTime();
|
||||||
|
snprintf(TimeFmtBuf, sizeof(TimeFmtBuf),
|
||||||
|
"%02d/%02d/%04d - %02d:%02d:%02d",
|
||||||
|
RtcTime->day,
|
||||||
|
RtcTime->month,
|
||||||
|
RtcTime->year + RtcTime->century*100,
|
||||||
|
RtcTime->hour,
|
||||||
|
RtcTime->min,
|
||||||
|
RtcTime->sec
|
||||||
|
);
|
||||||
|
return TimeFmtBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void UpdateCurTime(void)
|
||||||
|
{
|
||||||
|
ulong frequency = PIT_FREQUENCY;
|
||||||
|
uchar minRemain, hourRemain, dayRemain;
|
||||||
|
|
||||||
|
CurTime.sec =
|
||||||
|
(uchar)(((ulong)KeGetOriginTime()->sec + (Ticks / frequency)) % 60);
|
||||||
|
|
||||||
|
minRemain =
|
||||||
|
(uchar)(((ulong)KeGetOriginTime()->sec + (Ticks / frequency)) / 60);
|
||||||
|
|
||||||
|
CurTime.min =
|
||||||
|
(uchar)(((ulong)KeGetOriginTime()->min + minRemain) % 60);
|
||||||
|
|
||||||
|
hourRemain =
|
||||||
|
(uchar)(((ulong)KeGetOriginTime()->min + minRemain) / 60);
|
||||||
|
|
||||||
|
CurTime.hour =
|
||||||
|
(uchar)(((ulong)KeGetOriginTime()->hour + hourRemain) % 24);
|
||||||
|
|
||||||
|
dayRemain =
|
||||||
|
(uchar)(((ulong)KeGetOriginTime()->hour + hourRemain) / 24);
|
||||||
|
|
||||||
|
CurTime.day =
|
||||||
|
(uchar)(((ulong)KeGetOriginTime()->day + dayRemain) % 30);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Time_t* KeGetCurTime(void)
|
||||||
|
{
|
||||||
|
UpdateCurTime();
|
||||||
|
return &CurTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeSetCurTime(Time_t time)
|
||||||
|
{
|
||||||
|
CurTime = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint IsLeapYear(uint year)
|
||||||
|
{
|
||||||
|
if (!(year % 4)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return year % 100 == 0
|
||||||
|
? (year % 400 == 0)
|
||||||
|
: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint DaysInMonth(uint month, uint year)
|
||||||
|
{
|
||||||
|
return (month == 2)
|
||||||
|
? (28 + IsLeapYear(year))
|
||||||
|
: 31 - (month - 1) % 7 % 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ulong KeGetTimeStamp(void)
|
||||||
|
{
|
||||||
|
Time_t *time = KeGetCurTime();
|
||||||
|
|
||||||
|
uint dpy = 365 + IsLeapYear(time->year);
|
||||||
|
uint dim = DaysInMonth(time->month, time->year + time->century * 100);
|
||||||
|
|
||||||
|
return time->sec
|
||||||
|
+ time->min * 60
|
||||||
|
+ time->hour * 60 * 60
|
||||||
|
+ time->day * 24 * 60 * 60
|
||||||
|
+ time->month * dim * 24 * 60 * 60
|
||||||
|
+ (time->year + time->century * 100)
|
||||||
|
* dpy * 24 * 60 * 60;
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
|
|
||||||
static ulong Ticks = 0;
|
static ulong Ticks = 0;
|
||||||
static Time_t OriginTime;
|
static Time_t OriginTime;
|
||||||
static Time_t CurTime;
|
|
||||||
|
|
||||||
// TODO asnprintf()
|
// TODO asnprintf()
|
||||||
static char TimeFmtBuf[22] = { 0 };
|
static char TimeFmtBuf[22] = { 0 };
|
||||||
|
@ -158,14 +157,7 @@ static void GetTimeFromRTC(void)
|
||||||
OriginTime.hour = ((OriginTime.hour & 0x7)+ 10) % 24;
|
OriginTime.hour = ((OriginTime.hour & 0x7)+ 10) % 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
CurTime.sec = OriginTime.sec;
|
KeSetCurTime(OriginTime);
|
||||||
CurTime.min = OriginTime.min;
|
|
||||||
CurTime.hour = OriginTime.hour;
|
|
||||||
CurTime.weekday = OriginTime.weekday;
|
|
||||||
CurTime.day = OriginTime.day;
|
|
||||||
CurTime.month = OriginTime.month;
|
|
||||||
CurTime.year = OriginTime.year;
|
|
||||||
CurTime.century = OriginTime.century;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -179,95 +171,16 @@ static void HandleRTC(ISRFrame_t *regs)
|
||||||
KeSendEOItoPIC(0x28);
|
KeSendEOItoPIC(0x28);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *KeFormatCurTime(void)
|
|
||||||
{
|
|
||||||
Time_t *RtcTime = KeGetCurTime();
|
|
||||||
snprintf(TimeFmtBuf, sizeof(TimeFmtBuf),
|
|
||||||
"%02d/%02d/%04d - %02d:%02d:%02d",
|
|
||||||
RtcTime->day,
|
|
||||||
RtcTime->month,
|
|
||||||
RtcTime->year + RtcTime->century*100,
|
|
||||||
RtcTime->hour,
|
|
||||||
RtcTime->min,
|
|
||||||
RtcTime->sec
|
|
||||||
);
|
|
||||||
return TimeFmtBuf;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void UpdateCurTime(void)
|
|
||||||
{
|
|
||||||
ulong frequency = 32768 >> (RTC_RATE - 1);
|
|
||||||
uchar minRemain, hourRemain, dayRemain;
|
|
||||||
|
|
||||||
CurTime.sec =
|
|
||||||
(uchar)(((ulong)OriginTime.sec + (Ticks / frequency)) % 60);
|
|
||||||
|
|
||||||
minRemain =
|
|
||||||
(uchar)(((ulong)OriginTime.sec + (Ticks / frequency)) / 60);
|
|
||||||
|
|
||||||
CurTime.min =
|
|
||||||
(uchar)(((ulong)OriginTime.min + minRemain) % 60);
|
|
||||||
|
|
||||||
hourRemain =
|
|
||||||
(uchar)(((ulong)OriginTime.min + minRemain) / 60);
|
|
||||||
|
|
||||||
CurTime.hour =
|
|
||||||
(uchar)(((ulong)OriginTime.hour + hourRemain) % 24);
|
|
||||||
|
|
||||||
dayRemain =
|
|
||||||
(uchar)(((ulong)OriginTime.hour + hourRemain) / 24);
|
|
||||||
|
|
||||||
CurTime.day =
|
|
||||||
(uchar)(((ulong)OriginTime.day + dayRemain) % 30);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Time_t* KeGetCurTime(void)
|
|
||||||
{
|
|
||||||
UpdateCurTime();
|
|
||||||
return &CurTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint IsLeapYear(uint year)
|
|
||||||
{
|
|
||||||
if (!(year % 4)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return year % 100 == 0
|
|
||||||
? (year % 400 == 0)
|
|
||||||
: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint DaysInMonth(uint month, uint year)
|
|
||||||
{
|
|
||||||
return (month == 2)
|
|
||||||
? (28 + IsLeapYear(year))
|
|
||||||
: 31 - (month - 1) % 7 % 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong KeGetTimeStamp(void)
|
|
||||||
{
|
|
||||||
Time_t *time = KeGetCurTime();
|
|
||||||
|
|
||||||
uint dpy = 365 + IsLeapYear(time->year);
|
|
||||||
uint dim = DaysInMonth(time->month, time->year + time->century * 100);
|
|
||||||
|
|
||||||
return time->sec
|
|
||||||
+ time->min * 60
|
|
||||||
+ time->hour * 60 * 60
|
|
||||||
+ time->day * 24 * 60 * 60
|
|
||||||
+ time->month * dim * 24 * 60 * 60
|
|
||||||
+ (time->year + time->century * 100)
|
|
||||||
* dpy * 24 * 60 * 60;
|
|
||||||
}
|
|
||||||
|
|
||||||
ulong KeGetClockTicks(void)
|
ulong KeGetClockTicks(void)
|
||||||
{
|
{
|
||||||
return Ticks;
|
return Ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Time_t* KeGetOriginTime(void)
|
||||||
|
{
|
||||||
|
return &OriginTime;
|
||||||
|
}
|
||||||
|
|
||||||
void KeEnableRTC(void)
|
void KeEnableRTC(void)
|
||||||
{
|
{
|
||||||
ulong flags = KePauseIRQs();
|
ulong flags = KePauseIRQs();
|
||||||
|
|
|
@ -132,6 +132,14 @@ error_t CmdDie(int argc, char **argv, char *cmdline)
|
||||||
return EOK;
|
return EOK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error_t CmdSleep(int argc, char **argv, char *cmdline)
|
||||||
|
{
|
||||||
|
int delay = ShAtoi(argv[1]);
|
||||||
|
|
||||||
|
KeSleep(delay);
|
||||||
|
return EOK;
|
||||||
|
}
|
||||||
|
|
||||||
error_t CmdDumpATASect(int argc, char **argv, char *cmdline)
|
error_t CmdDumpATASect(int argc, char **argv, char *cmdline)
|
||||||
{
|
{
|
||||||
char sector[512] = {0};
|
char sector[512] = {0};
|
||||||
|
@ -317,6 +325,7 @@ Command_t shcmdtable[] =
|
||||||
{ "march", CmdStarWars, "Play the Imperial March" },
|
{ "march", CmdStarWars, "Play the Imperial March" },
|
||||||
{ "time", CmdTime, "Print time" },
|
{ "time", CmdTime, "Print time" },
|
||||||
{ "ver", CmdVersion, "Version and legal infos" },
|
{ "ver", CmdVersion, "Version and legal infos" },
|
||||||
|
{ "sleep", CmdSleep, "Sleep x ms" },
|
||||||
{ NULL, NULL, NULL }
|
{ NULL, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue