diff --git a/src/add-ons/Jamfile b/src/add-ons/Jamfile index 1bf82744a6..8d3dabfb79 100644 --- a/src/add-ons/Jamfile +++ b/src/add-ons/Jamfile @@ -1,5 +1,82 @@ SubDir OBOS_TOP src add-ons ; +KernelLd + zero + : + <$(SOURCE_GRIST)!kernel!drivers!common>zero.o + kernel.so + : + $(OBOS_TOP)/src/kernel/core/addons/ldscripts/$(OBOS_ARCH)/addon.ld + : + -Bdynamic -shared + : + : + addons/drivers/dev/zero + ; + +KernelLd + null + : + <$(SOURCE_GRIST)!kernel!drivers!common>null.o + kernel.so + : + $(OBOS_TOP)/src/kernel/core/addons/ldscripts/$(OBOS_ARCH)/addon.ld + : + -Bdynamic -shared + : + : + addons/drivers/dev/null + ; + +KernelLd + digit + : + <$(SOURCE_GRIST)!kernel!drivers!common>digit.o + kernel.so + : + $(OBOS_TOP)/src/kernel/core/addons/ldscripts/$(OBOS_ARCH)/addon.ld + : + -Bdynamic -shared + : + : + addons/drivers/dev/digit + ; + +KernelLd + random + : + <$(SOURCE_GRIST)!kernel!drivers!random>driver.o + kernel.so + : + $(OBOS_TOP)/src/kernel/core/addons/ldscripts/$(OBOS_ARCH)/addon.ld + : + -Bdynamic -shared + : + : + addons/drivers/dev/random + ; + +# This needs to be fixed once the various headers are fixed. +#KernelLd +# ac97 +# : +# <$(SOURCE_GRIST)!kernel!drivers!audio!ac97!ich>ac97_multi.o +# <$(SOURCE_GRIST)!kernel!drivers!audio!ac97!ich>config.o +# <$(SOURCE_GRIST)!kernel!drivers!audio!ac97!ich>debug.o +# <$(SOURCE_GRIST)!kernel!drivers!audio!ac97!ich>ich.o +# <$(SOURCE_GRIST)!kernel!drivers!audio!ac97!ich>io.o +# <$(SOURCE_GRIST)!kernel!drivers!audio!ac97!ich>util.o +# kernel.so +# : +# $(OBOS_TOP)/src/kernel/core/addons/ldscripts/$(OBOS_ARCH)/addon.ld +# : +# -Bdynamic -shared +# : +# : +# addons/drivers/dev/audio/ac97 +# ; + + SubInclude OBOS_TOP src add-ons input_server ; SubInclude OBOS_TOP src add-ons kernel ; SubInclude OBOS_TOP src add-ons media ; diff --git a/src/add-ons/kernel/Jamfile b/src/add-ons/kernel/Jamfile index 65e5e82587..13b4fe4efb 100644 --- a/src/add-ons/kernel/Jamfile +++ b/src/add-ons/kernel/Jamfile @@ -3,3 +3,4 @@ SubDir OBOS_TOP src add-ons kernel ; SubInclude OBOS_TOP src add-ons kernel drivers ; SubInclude OBOS_TOP src add-ons kernel file_systems ; SubInclude OBOS_TOP src add-ons kernel net ; + diff --git a/src/add-ons/kernel/drivers/Jamfile b/src/add-ons/kernel/drivers/Jamfile index 3b81b68349..142d7fe621 100644 --- a/src/add-ons/kernel/drivers/Jamfile +++ b/src/add-ons/kernel/drivers/Jamfile @@ -1,3 +1,6 @@ SubDir OBOS_TOP src add-ons kernel drivers ; -SubInclude OBOS_TOP src add-ons kernel drivers audio ; \ No newline at end of file +SubInclude OBOS_TOP src add-ons kernel drivers audio ; +SubInclude OBOS_TOP src add-ons kernel drivers common ; +SubInclude OBOS_TOP src add-ons kernel drivers random ; + diff --git a/src/add-ons/kernel/drivers/audio/ac97/ich/Jamfile b/src/add-ons/kernel/drivers/audio/ac97/ich/Jamfile index 815ff13bab..33248bd9ee 100644 --- a/src/add-ons/kernel/drivers/audio/ac97/ich/Jamfile +++ b/src/add-ons/kernel/drivers/audio/ac97/ich/Jamfile @@ -11,6 +11,18 @@ Addon ich_ac97 : [ FDirName kernel drivers bin ] : util.c ; +# For OpenBeOS we should be building the driver objects this way. +#KernelObjects +# ac97_multi.c +# config.c +# debug.c +# ich.c +# io.c +# util.c +# : +# -fno-pic -D_KERNEL_MODE +# ; + LinkSharedOSLibs ich_ac97 : /boot/develop/lib/x86/_KERNEL_ ; # Link to kernel/drivers/dev/audio/multi diff --git a/src/add-ons/kernel/drivers/common/Jamfile b/src/add-ons/kernel/drivers/common/Jamfile new file mode 100644 index 0000000000..d9387194f6 --- /dev/null +++ b/src/add-ons/kernel/drivers/common/Jamfile @@ -0,0 +1,4 @@ +SubDir OBOS_TOP src add-ons kernel drivers common ; + +KernelObjects null.c zero.c digit.c : -fno-pic ; + diff --git a/src/add-ons/kernel/drivers/common/digit.c b/src/add-ons/kernel/drivers/common/digit.c new file mode 100644 index 0000000000..b313af8e6e --- /dev/null +++ b/src/add-ons/kernel/drivers/common/digit.c @@ -0,0 +1,172 @@ +/******************************************************************************* +/ +/ File: driver.c +/ +/ Description: The digit driver allows a client to read 16 bytes of data. +/ Each byte has the same value (by default 0); the client +/ can change this value with write or ioctl commands. +/ +/ Copyright 1999, Be Incorporated. All Rights Reserved. +/ This file may be used under the terms of the Be Sample Code License. +/ +*******************************************************************************/ + +#include +#include +#include +#include +#include +#include + +#define DPRINTF(a) dprintf("digit: "); dprintf a + +#define MAX_SIZE 16 +#define DEVICE_NAME "misc/digit" + +#define TOUCH(x) ((void)x) + +/*********************************/ + +struct digit_state { + uchar value; +}; + +static status_t +digit_open(const char *name, uint32 mode, void **cookie) +{ + struct digit_state *s; + + TOUCH(name); TOUCH(mode); + + DPRINTF(("open\n")); + + s = (struct digit_state*) kmalloc(sizeof(*s)); + if (!s) + return ENOMEM; + + s->value = 0; + + *cookie = s; + + return 0; +} + +static status_t +digit_close(void *cookie) +{ + DPRINTF(("close\n")); + + TOUCH(cookie); + + return 0; +} + +static status_t +digit_free(void *cookie) +{ + DPRINTF(("free\n")); + + kfree(cookie); + + return 0; +} + +static status_t +digit_ioctl(void *cookie, uint32 op, void *data, size_t len) +{ + TOUCH(len); + + DPRINTF(("ioctl\n")); + + if (op == 'set ') { + struct digit_state *s = (struct digit_state *)cookie; + s->value = *(uchar *)data; + DPRINTF(("Set digit to %2.2x\n", s->value)); + return 0; + } + + return ENOSYS; +} + +static ssize_t +digit_read(void *cookie, off_t pos, void *buffer, size_t *len) +{ + struct digit_state *s = (struct digit_state *)cookie; + + DPRINTF(("read\n")); + + if (pos >= MAX_SIZE) { + *len = 0; + return ESPIPE; + } else if (pos + *len > MAX_SIZE) + *len = (size_t)(MAX_SIZE - pos); + + if (*len) + memset(buffer, s->value, *len); + + return 0; +} + +static ssize_t +digit_write(void *cookie, off_t pos, const void *buffer, size_t *len) +{ + struct digit_state *s = (struct digit_state *)cookie; + + TOUCH(pos); + + s->value = ((uchar *)buffer)[*len - 1]; + + DPRINTF(("write: set digit to %2.2x\n", s->value)); + + return 0; +} + +/***************************/ + +status_t init_hardware() +{ + DPRINTF(("Do you digit?\n")); + return 0; +} + +const char **publish_devices(void) +{ + static const char *devices[] = { + DEVICE_NAME, NULL + }; + + return devices; +} + +device_hooks *find_device(const char *name) +{ + static device_hooks hooks = { + &digit_open, + &digit_close, + &digit_free, + &digit_ioctl, + &digit_read, + &digit_write, + /* Leave select/deselect/readv/writev undefined. The kernel will + * use its own default implementation. The basic hooks above this + * line MUST be defined, however. */ + NULL, + NULL, +// NULL, +// NULL + }; + + if (!strcmp(name, DEVICE_NAME)) + return &hooks; + + return NULL; +} + +status_t init_driver() +{ + return 0; +} + +void uninit_driver() +{ +} diff --git a/src/add-ons/kernel/drivers/common/null.c b/src/add-ons/kernel/drivers/common/null.c new file mode 100644 index 0000000000..acb8bafca1 --- /dev/null +++ b/src/add-ons/kernel/drivers/common/null.c @@ -0,0 +1,93 @@ +/* +** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "null" + +static int null_open(const char *name, uint32 flags, void * *cookie) +{ + *cookie = NULL; + return 0; +} + +static int null_close(void * cookie) +{ + return 0; +} + +static int null_freecookie(void * cookie) +{ + return 0; +} + +static int null_ioctl(void * cookie, uint32 op, void *buf, size_t len) +{ + return EPERM; +} + +static ssize_t null_read(void * cookie, off_t pos, void *buf, size_t *len) +{ + return 0; +} + +static ssize_t null_write(void * cookie, off_t pos, const void *buf, size_t *len) +{ + return 0; +} + +status_t init_hardware() +{ + return 0; +} + +const char **publish_devices(void) +{ + static const char *devices[] = { + DEVICE_NAME, + NULL + }; + + return devices; +} + +device_hooks *find_device(const char *name) +{ + static device_hooks hooks = { + &null_open, + &null_close, + &null_freecookie, + &null_ioctl, + &null_read, + &null_write, + /* Leave select/deselect/readv/writev undefined. The kernel will + * use its own default implementation. The basic hooks above this + * line MUST be defined, however. */ + NULL, + NULL, + NULL, + NULL + }; + + if (!strcmp(name, DEVICE_NAME)) + return &hooks; + + return NULL; +} + +status_t init_driver() +{ + return 0; +} + +void uninit_driver() +{ +} + diff --git a/src/add-ons/kernel/drivers/common/zero.c b/src/add-ons/kernel/drivers/common/zero.c new file mode 100644 index 0000000000..71d5a8272a --- /dev/null +++ b/src/add-ons/kernel/drivers/common/zero.c @@ -0,0 +1,101 @@ +/* +** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. +** Distributed under the terms of the NewOS License. +*/ +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_NAME "zero" + +static int zero_open(const char *name, uint32 flags, void **cookie) +{ + *cookie = NULL; + return 0; +} + +static int zero_close(void * cookie) +{ + return 0; +} + +static int zero_freecookie(void * cookie) +{ + return 0; +} + +static int zero_ioctl(void * cookie, uint32 op, void *buf, size_t len) +{ + return EPERM; +} + +static ssize_t zero_read(void * cookie, off_t pos, void *buf, size_t *len) +{ + int rc; + + rc = user_memset(buf, 0, *len); + if(rc < 0) + return rc; + + return 0; +} + +static ssize_t zero_write(void * cookie, off_t pos, const void *buf, size_t *len) +{ + return 0; +} + +status_t init_hardware() +{ + return 0; +} + +const char **publish_devices(void) +{ + static const char *devices[] = { + DEVICE_NAME, + NULL + }; + + return devices; +} + +device_hooks *find_device(const char *name) +{ + static device_hooks hooks = { + &zero_open, + &zero_close, + &zero_freecookie, + &zero_ioctl, + &zero_read, + &zero_write, + /* Leave select/deselect/readv/writev undefined. The kernel will + * use its own default implementation. The basic hooks above this + * line MUST be defined, however. */ + NULL, + NULL, + NULL, + NULL + }; + + if (!strcmp(name, DEVICE_NAME)) + return &hooks; + + return NULL; +} + +status_t init_driver() +{ + return 0; +} + +void uninit_driver() +{ +} + + diff --git a/src/add-ons/kernel/drivers/random/Jamfile b/src/add-ons/kernel/drivers/random/Jamfile new file mode 100644 index 0000000000..e1a0146ec3 --- /dev/null +++ b/src/add-ons/kernel/drivers/random/Jamfile @@ -0,0 +1,8 @@ +SubDir OBOS_TOP src add-ons kernel drivers random ; + +KernelObjects + <$(SOURCE_GRIST)>driver.c + : + -fno-pic -D_KERNEL_MODE -O99 -mpentiumpro -march=pentiumpro -Wno-missing-prototypes + ; + diff --git a/src/add-ons/kernel/drivers/random/driver.c b/src/add-ons/kernel/drivers/random/driver.c new file mode 100644 index 0000000000..2e7063ca70 --- /dev/null +++ b/src/add-ons/kernel/drivers/random/driver.c @@ -0,0 +1,446 @@ +/* Yarrow Random Number Generator (True Randomness Achieved in Software) * + * Copyright (c) 1998-2000 by Yarrow Charnot, Identikey + * All Lefts, Rights, Ups, Downs, Forwards, Backwards, Pasts and Futures Reserved * + */ + +/* Made into a BeOS /dev/random and /dev/urandom by Daniel Berlin */ +/* Adapted for OpenBeOS by david reid */ + +/* To compile on Sun: gcc -m32 -msupersparc -mcpu=v8 -g -O3 -finline-functions -Wa,-xarch= + v8plusc -Winline -lrt */ +/* To compile on Intel, MSVC with /G6 /Gr /O2 and with either /MT or /MD is recommended */ +/* If you want to export any of the following functions, you know what to do */ + + +#include +#include +#include +#include +#include + +#define thread_yield() snooze(10) +#define _rmtmp() + +#define __int8 char +#define __int16 short +#define __int32 long +#define __int64 long long +//#define __cdecl +#define __fastcall +#define __forceinline __inline__ +#define ASM __asm__ +#define _lrotr(x, n) ((((unsigned __int32)(x)) >> ((int) ((n) & 31))) | (((unsigned __int32)(x)) << ((int) ((32 - ((n) & 31)))))) +#define _lrotl(x, n) ((((unsigned __int32)(x)) << ((int) ((n) & 31))) | (((unsigned __int32)(x)) >> ((int) ((32 - ((n) & 31)))))) + +#if defined (_M_IX86) || defined (__i386__) && defined (__GNUC__) + +static volatile __inline__ unsigned long long clock_counter (void) +{ + return system_time(); /* eventually real_time_clock_usecs() ? */ +} + +#elif defined (sparc) || defined (__sparc) || defined (sun) || defined (__sun) && defined (__GNUC__) +static __inline unsigned long long clock_counter (void) +{ + register unsigned long x, y; + __asm__ __volatile__ ("rd %%tick, %0; clruw %0, %1; srlx %0, 32, %0" : "=r" (x), "=r" (y) : "0" (x), "1" (y)); + return ((unsigned long long) x << 32) | y; +} +#else +extern unsigned __int64 clock_counter (void); /* one of the above or any other clock + counter function compiled separately */ +#endif + +#define rotr32(x, n) _lrotr (x, n) +#define rotl32(x, n) _lrotl (x, n) + +#define bswap32(x) ((rotl32 ((unsigned __int32)(x), 8) & 0x00ff00ff) | (rotr32 ((unsigned __int32)(x), 8) & 0xff00ff00)) + +#ifndef _OCTET_ +#define _OCTET_ +typedef union _OCTET +{ + unsigned __int64 Q[1]; + unsigned __int32 D[2]; + unsigned __int16 W[4]; + unsigned __int8 B[8]; +} OCTET; +#endif + +#define NK 257 /* internal state size */ +#define NI 120 /* seed in increment */ +#define NA 70 /* rand out increment A */ +#define NB 139 /* rand out increment B */ +typedef struct _ch_randgen +{ + OCTET ira[NK]; /* numbers live here */ + OCTET *seedptr; /* next seed pointer */ + OCTET *rndptrA; /* randomizing pointer #1 */ + OCTET *rndptrB; /* randomizing pointer #2 */ + OCTET *rndptrX; /* main randout pointer */ + OCTET rndLeft; /* left rand accumulator */ + OCTET rndRite; /* rite rand accumulator */ +} ch_randgen; + +extern void hash_block(const unsigned char *block, const unsigned int block_byte_size, unsigned char *md); + + +#define HASH_BITS 160 /* I use Tiger. Modify it to match your HASH */ +#define HASH_BLOCK_BITS 512 /* I use Tiger. Modify it to match your HASH */ +#define HASH_BYTES (HASH_BITS / 8) +#define HASH_BLOCK_BYTES (HASH_BLOCK_BITS / 8) +#define HASH_OCTETS (HASH_BITS / 64) +#define HASH_BLOCK_OCTETS (HASH_BLOCK_BITS / 64) +/* attach by Yarrow Charnot. attaches x to y. can be seen as about 2-3 rounds of RC6 encryption + */ +__inline__ void __fastcall attach (OCTET *y, const OCTET *x, const unsigned __int32 anyA, const unsigned __int32 anyB, const unsigned __int32 oddC, const unsigned __int32 + oddD) +{ + register OCTET _x; + register OCTET _y; + _x.D[0] = x->D[0]; + _x.D[1] = x->D[1]; + _y.D[0] = y->D[0]; + _y.D[1] = y->D[1]; + _x.D[0] = rotl32 (((bswap32(_x.D[0]) | 1) * x->D[1]), 5); + _x.D[1] = rotl32 ((bswap32 (_x.D[1]) | 1) * x->D[0], 5); + _y.D[0] = (bswap32 (rotl32 (_y.D[0] ^ _x.D[0], _x.D[1])) + anyA) * oddC; + _y.D[1] = (bswap32 (rotl32 (_y.D[1] ^ _x.D[1], _x.D[0])) + anyB) * oddD; + y->D[1] = _y.D[0]; + y->D[0] = _y.D[1]; +} +/* detach by Yarrow Charnot. detaches x from y. can be seen as about 2-3 rounds of RC6 + decryption */ +__forceinline void __fastcall detach (OCTET *y, const OCTET *x, const unsigned __int32 + sameA, const unsigned __int32 sameB, const unsigned __int32 invoddC, const unsigned __int32 + invoddD) +{ + register OCTET _x; + register OCTET _y; + _x.D[0] = x->D[0]; + _x.D[1] = x->D[1]; + _y.D[0] = y->D[1]; + _y.D[1] = y->D[0]; + _x.D[0] = rotl32 ((bswap32 (_x.D[0]) | 1) * x->D[1], 5); + _x.D[1] = rotl32 ((bswap32 (_x.D[1]) | 1) * x->D[0], 5); + _y.D[0] = rotr32 (bswap32 (_y.D[0] * invoddC - sameA), _x.D[1]) ^ _x.D[0]; + _y.D[1] = rotr32 (bswap32 (_y.D[1] * invoddD - sameB), _x.D[0]) ^ _x.D[1]; + y->D[0] = _y.D[0]; + y->D[1] = _y.D[1]; +} +/* QUICKLY seeds in a 64 bit number, modified so that a subsequent call really "stirs" in another + seed value (no bullshit XOR here!) */ +__inline void chseed (ch_randgen *prandgen, const unsigned __int64 seed) +{ + prandgen->seedptr += NI; + if (prandgen->seedptr >= (prandgen->ira + NK)) prandgen->seedptr -= NK; + attach (prandgen->seedptr, (OCTET *) &seed, 0x213D42F6U, 0x6552DAF9U, + 0x2E496B7BU, 0x1749A255U); +} +/* The heart of Yarrow 2000 Chuma Random Number Generator: fast and reliable randomness + collection. */ +/* thread yielding function is the most OPTIMAL source of randomness combined with a clock + counter. */ +/* it doesn't have to switch to another thread, the call itself is random enough. test it yourself. */ +/* this FASTEST way to collect minimal randomness on each step couldn't use the processor + any LESS. */ +/* even functions based on just creation of threads and their destruction can not compare by + speed. */ +/* temporary file creation is just a little extra thwart to bewilder the processor cache and pipes. */ /* if you make clock_counter return all 0's, still produces a stream indistinguishable from + random. */ +volatile void reseed (ch_randgen *prandgen, const unsigned int inittimes) +{ + volatile unsigned int i, j; + OCTET x, y; + for (j = inittimes; j; j--) + { + for (i = NK * inittimes; i; i--) + { + thread_yield (); + y.Q[0] += clock_counter (); + attach (&x, &y, 0x52437EFFU, 0x026A4CEBU, 0xD9E66AC9U, 0x56E5A975U); + attach (&y, &x, 0xC70B8B41U, 0x9126B036U, 0x36CC6FDBU, 0x31D477F7U); + chseed (prandgen, y.Q[0]); + } + } +} +/* returns a 64 bit of Yarrow 2000 Chuma RNG random number */ +volatile __inline unsigned __int64 chrand (ch_randgen *prandgen) +{ + prandgen->rndptrX ++; + prandgen->rndptrA += NA; + prandgen->rndptrB += NB; + if (prandgen->rndptrX >= (prandgen->ira + NK)) + { + prandgen->rndptrX -= NK; + reseed (prandgen, 1); + } + if (prandgen->rndptrA >= (prandgen->ira + NK)) prandgen->rndptrA -= NK; + if (prandgen->rndptrB >= (prandgen->ira + NK)) prandgen->rndptrB -= NK; + attach (&prandgen->rndLeft, prandgen->rndptrX, prandgen->rndptrA->D[0], prandgen + ->rndptrA->D[1], 0x49A3BC71UL, 0x60E285FDUL); + attach (&prandgen->rndRite, &prandgen->rndLeft, prandgen->rndptrB->D[0], prandgen + ->rndptrB->D[1], 0xC366A5FDUL, 0x20C763EFUL); + chseed (prandgen, prandgen->rndRite.Q[0]); + return prandgen->rndRite.Q[0] ^ prandgen->rndLeft.Q[0]; +} +/* returns a 32 bit random number */ +volatile __inline unsigned __int32 chrand32 (ch_randgen *prandgen) +{ + OCTET r = {{chrand (prandgen)}}; + return r.D[0] ^ r.D[1]; +} +/* returns an 8 bit random number */ +volatile __inline unsigned __int8 chrand8 (ch_randgen *prandgen) +{ + OCTET r = {{chrand(prandgen)}}; + return r.B[0] ^ r.B[1] ^ r.B[2] ^ r.B[3] ^ r.B[4] ^ r.B[5] ^ r.B[6] ^ r.B[7] ; +} + +/* generates a cryptographically secure random big number 0 <= x < 32^n */ +/* automatically reseeds if necessary or if requested 1/16 of the internal state or more */ +/* + __inline void bigrand (ch_randgen *prandgen, unsigned __int32 *x, unsigned __int32 n) + { + unsigned int i; + OCTET block[HASH_BLOCK_OCTETS]; + OCTET hash[HASH_OCTETS]; + OCTET *j; + if (n >= NK/8) reseed (prandgen, 1); + for (*x++ = n; (signed) n > 0; ) + { + for (i = 0; i < HASH_BLOCK_OCTETS; i++) block->Q[i] += chrand (prandgen) + hash + ->Q[i % HASH_OCTETS]; + hash_block (block->B, HASH_BLOCK_BYTES, hash->B); + for (i = HASH_OCTETS, j = hash; i && ((signed) n > 0); i--, j++, x += 2, n -= 2) + { + attach ((OCTET *) &x, j, 0x0AEF7ED2U, 0x3F85C5C1U, 0xD3EFB373U, + 0x13ECF0B9U); + } + } + } + */ +/* Initializes Yarrow 2000 Chuma Random Number Generator */ +/* reseeding about 8 times prior to the first use is recommended. */ +/* more than 16 will probably be a bit too much as time increases by n^2 */ +__inline ch_randgen *new_chrand (const unsigned int inittimes) +{ + ch_randgen *prandgen; + prandgen = (ch_randgen *)kmalloc (sizeof (ch_randgen)); + prandgen->seedptr = prandgen->ira; + prandgen->rndptrX = prandgen->ira; + prandgen->rndptrA = prandgen->ira; + prandgen->rndptrB = prandgen->ira; + prandgen->rndLeft.Q[0] = 0x1A4B385C72D69E0FUL; + prandgen->rndRite.Q[0] = 0x9C805FE7361A42DBUL; + reseed (prandgen, inittimes); + prandgen->seedptr = prandgen->ira + chrand (prandgen) % NK; + prandgen->rndptrX = prandgen->ira + chrand (prandgen) % NK; + prandgen->rndptrA = prandgen->ira + chrand (prandgen) % NK; + prandgen->rndptrB = prandgen->ira + chrand (prandgen) % NK; + return prandgen; +} +/* Clean up after chuma */ +__inline void kill_chrand (ch_randgen *randgen) +{ + memset (randgen, 0, sizeof (ch_randgen)); + kfree (randgen); +} +/* ++++++++++ + driver.c + A skeletal device driver + +++++ */ + +//#include +#include +#include +#include +#include +static ch_randgen *rng; +static unsigned int randcount=0; +static sem_id rand_mutex; +#define DRIVER_NAME "random" +#define DEVICE_NAME "random" +#define DEVICE_NAME2 "urandom" +int32 api_version = B_CUR_DRIVER_API_VERSION; + +/* ---------- + init_hardware - called once the first time the driver is loaded + ----- */ + + +status_t init_hardware (void) +{ + dprintf (DRIVER_NAME ": init_hardware()\n"); + return B_OK; +} + + +/* ---------- + init_driver - optional function - called every time the driver + is loaded. + ----- */ + + +status_t init_driver (void) +{ + rng = new_chrand(8); + rand_mutex = create_sem(1, "RNG semaphore"); + dprintf (DRIVER_NAME ": init_driver()\n"); + return B_OK; +} + + +/* ---------- + uninit_driver - optional function - called every time the driver + is unloaded + ----- */ + +void uninit_driver (void) +{ + kill_chrand(rng); + delete_sem(rand_mutex); + dprintf (DRIVER_NAME ": uninit_driver()\n"); +} + + +/* ---------- + my_device_open - handle open() calls + ----- */ + +static status_t my_device_open (const char *name, uint32 flags, void** cookie) +{ + dprintf (DRIVER_NAME ": open(\"%s\")\n", name); + return B_OK; +} + + +/* ---------- + my_device_read - handle read() calls + ----- */ + +static ssize_t my_device_read (void* cookie, off_t position, void *buf, size_t* num_bytes) +{ + int32* buffer = (int32 *)buf; + unsigned char *buf8 = (unsigned char *)buf; + int i,j; + acquire_sem(rand_mutex); + randcount += *num_bytes; + + /* Reseed if we have or are gonna use up > 1/16th the entropy around */ + if (randcount >= NK/8) { + randcount = 0; + reseed (rng, 1); + } + + /* Yes, i know this is not the way we should do it. What we really should do is + * take the md5 or sha1 hash of the state of the pool, and return that. Someday. */ + for(i = 0 ; i < (*num_bytes)/4 ; i++) + buffer[i] = chrand32(rng); + for(j = 0 ; j < (*num_bytes) % 4; j++) + buf8[(i*4)+j] = chrand8(rng); + release_sem(rand_mutex); + + return B_OK; +} + + +/* ---------- + my_device_write - handle write() calls + ----- */ + +static ssize_t my_device_write (void* cookie, off_t position, const void* buf, size_t* num_bytes) +{ + return B_OK; +} + + +/* ---------- + my_device_control - handle ioctl calls + ----- */ + +static status_t my_device_control (void* cookie, uint32 op, void* arg, size_t len) +{ + /*dprintf (DRIVER_NAME ": ioctl(%d)\n", op);*/ + return B_ERROR; +} + + +/* ---------- + my_device_close - handle close() calls + ----- */ + + +static status_t my_device_close (void* cookie) +{ + dprintf (DRIVER_NAME ": close()\n"); + return B_OK; +} + + +/* ----- + my_device_free - called after the last device is closed, and after + all i/o is complete. + ----- */ + + +static status_t my_device_free (void* cookie) +{ + dprintf (DRIVER_NAME ": free()\n"); + return B_OK; +} + + +/* ----- + null-terminated array of device names supported by this driver + ----- */ + +static const char *my_device_name[] = { + DEVICE_NAME, + DEVICE_NAME2, + NULL +}; + +/* ----- + function pointers for the device hooks entry points + ----- */ + +static device_hooks my_device_hooks = { + my_device_open, /* -> open entry point */ + my_device_close, /* -> close entry point */ + my_device_free, /* -> free cookie */ + my_device_control, /* -> control entry point */ + my_device_read, /* -> read entry point */ + my_device_write, /* -> write entry point */ + NULL, + NULL, + NULL, + NULL +}; + +/* ---------- + publish_devices - return a null-terminated array of devices + supported by this driver. + ----- */ + + +const char **publish_devices() +{ + dprintf (DRIVER_NAME ": publish_devices()\n"); + return my_device_name; +} + +/* ---------- + find_device - return ptr to device hooks structure for a + given device name + ----- */ +device_hooks *find_device(const char* name) +{ + int i; + dprintf (DRIVER_NAME ": find_device(\"%s\")\n", name); + for (i = 0; my_device_name[i] != NULL; i++) + if (strcmp (name, my_device_name [i]) == 0) + return &my_device_hooks; + return NULL; +} +