00001
00002
00003
00004
00005
00006 #include "../drivers.h"
00007 #include "../libdriver/driver.h"
00008 #include <sys/ioc_memory.h>
00009 #include "../../kernel/const.h"
00010 #include "../../kernel/config.h"
00011 #include "../../kernel/type.h"
00012
00013 #include "assert.h"
00014 #include "random.h"
00015
00016 #define NR_DEVS 1
00017 # define RANDOM_DEV 0
00018
00019 #define KRANDOM_PERIOD 1
00020
00021 PRIVATE struct device m_geom[NR_DEVS];
00022 PRIVATE int m_device;
00023
00024 extern int errno;
00025
00026 FORWARD _PROTOTYPE( char *r_name, (void) );
00027 FORWARD _PROTOTYPE( struct device *r_prepare, (int device) );
00028 FORWARD _PROTOTYPE( int r_transfer, (int proc_nr, int opcode, off_t position,
00029 iovec_t *iov, unsigned nr_req) );
00030 FORWARD _PROTOTYPE( int r_do_open, (struct driver *dp, message *m_ptr) );
00031 FORWARD _PROTOTYPE( void r_init, (void) );
00032 FORWARD _PROTOTYPE( int r_ioctl, (struct driver *dp, message *m_ptr) );
00033 FORWARD _PROTOTYPE( void r_geometry, (struct partition *entry) );
00034 FORWARD _PROTOTYPE( void r_random, (struct driver *dp, message *m_ptr) );
00035
00036
00037 PRIVATE struct driver r_dtab = {
00038 r_name,
00039 r_do_open,
00040 do_nop,
00041 r_ioctl,
00042 r_prepare,
00043 r_transfer,
00044 nop_cleanup,
00045 r_geometry,
00046 nop_signal,
00047 r_random,
00048 nop_cancel,
00049 nop_select,
00050 NULL,
00051 NULL
00052 };
00053
00054
00055 #define RANDOM_BUF_SIZE 1024
00056 PRIVATE char random_buf[RANDOM_BUF_SIZE];
00057
00058
00059
00060
00061 PUBLIC int main(void)
00062 {
00063 r_init();
00064 driver_task(&r_dtab);
00065 return(OK);
00066 }
00067
00068
00069
00070
00071 PRIVATE char *r_name()
00072 {
00073
00074 static char name[] = "random";
00075 return name;
00076 }
00077
00078
00079
00080
00081 PRIVATE struct device *r_prepare(device)
00082 int device;
00083 {
00084
00085
00086 if (device < 0 || device >= NR_DEVS) return(NIL_DEV);
00087 m_device = device;
00088
00089 return(&m_geom[device]);
00090 }
00091
00092
00093
00094
00095 PRIVATE int r_transfer(proc_nr, opcode, position, iov, nr_req)
00096 int proc_nr;
00097 int opcode;
00098 off_t position;
00099 iovec_t *iov;
00100 unsigned nr_req;
00101 {
00102
00103 unsigned count, left, chunk;
00104 vir_bytes user_vir;
00105 struct device *dv;
00106 unsigned long dv_size;
00107
00108
00109 dv = &m_geom[m_device];
00110 dv_size = cv64ul(dv->dv_size);
00111
00112 while (nr_req > 0) {
00113
00114
00115 count = iov->iov_size;
00116 user_vir = iov->iov_addr;
00117
00118 switch (m_device) {
00119
00120
00121 case RANDOM_DEV:
00122 if (opcode == DEV_GATHER && !random_isseeded())
00123 return(EAGAIN);
00124 left = count;
00125 while (left > 0) {
00126 chunk = (left > RANDOM_BUF_SIZE) ? RANDOM_BUF_SIZE : left;
00127 if (opcode == DEV_GATHER) {
00128 random_getbytes(random_buf, chunk);
00129 sys_vircopy(SELF, D, (vir_bytes) random_buf,
00130 proc_nr, D, user_vir, chunk);
00131 } else if (opcode == DEV_SCATTER) {
00132 sys_vircopy(proc_nr, D, user_vir,
00133 SELF, D, (vir_bytes) random_buf, chunk);
00134 random_putbytes(random_buf, chunk);
00135 }
00136 user_vir += chunk;
00137 left -= chunk;
00138 }
00139 break;
00140
00141
00142 default:
00143 return(EINVAL);
00144 }
00145
00146
00147 position += count;
00148 iov->iov_addr += count;
00149 if ((iov->iov_size -= count) == 0) { iov++; nr_req--; }
00150
00151 }
00152 return(OK);
00153 }
00154
00155
00156
00157
00158 PRIVATE int r_do_open(dp, m_ptr)
00159 struct driver *dp;
00160 message *m_ptr;
00161 {
00162
00163
00164 if (r_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
00165
00166 return(OK);
00167 }
00168
00169
00170
00171
00172 PRIVATE void r_init()
00173 {
00174
00175 random_init();
00176 r_random(NULL, NULL);
00177 }
00178
00179
00180
00181
00182 PRIVATE int r_ioctl(dp, m_ptr)
00183 struct driver *dp;
00184 message *m_ptr;
00185 {
00186 struct device *dv;
00187 if ((dv = r_prepare(m_ptr->DEVICE)) == NIL_DEV) return(ENXIO);
00188
00189 switch (m_ptr->REQUEST) {
00190
00191 default:
00192 return(do_diocntl(&r_dtab, m_ptr));
00193 }
00194 return(OK);
00195 }
00196
00197
00198
00199
00200 PRIVATE void r_random(dp, m_ptr)
00201 struct driver *dp;
00202 message *m_ptr;
00203 {
00204
00205 int i, s, r_next, r_size, r_high;
00206 struct randomness krandom;
00207
00208 if (OK != (s=sys_getrandomness(&krandom)))
00209 report("RANDOM", "sys_getrandomness failed", s);
00210
00211 for (i= 0; i<RANDOM_SOURCES; i++)
00212 {
00213 r_next= krandom.bin[i].r_next;
00214 r_size= krandom.bin[i].r_size;
00215 r_high= r_next+r_size;
00216 if (r_high <= RANDOM_ELEMENTS)
00217 {
00218 random_update(i, &krandom.bin[i].r_buf[r_next], r_size);
00219 }
00220 else
00221 {
00222 assert(r_next < RANDOM_ELEMENTS);
00223 random_update(i, &krandom.bin[i].r_buf[r_next],
00224 RANDOM_ELEMENTS-r_next);
00225 random_update(i, &krandom.bin[i].r_buf[0],
00226 r_high-RANDOM_ELEMENTS);
00227 }
00228 }
00229
00230
00231 if (OK != (s=sys_setalarm(KRANDOM_PERIOD, 0)))
00232 report("RANDOM", "sys_setalarm failed", s);
00233 }
00234
00235
00236
00237
00238 PRIVATE void r_geometry(entry)
00239 struct partition *entry;
00240 {
00241
00242 entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32);
00243 entry->heads = 64;
00244 entry->sectors = 32;
00245 }
00246