1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
#include "errno.h"
#include "globals.h"
#include "util/debug.h"
#include "util/string.h"
#include "mm/kmalloc.h"
#include "mm/mobj.h"
#include "drivers/chardev.h"
#include "vm/anon.h"
#include "fs/vnode.h"
static ssize_t null_read(chardev_t *dev, size_t pos, void *buf, size_t count);
static ssize_t null_write(chardev_t *dev, size_t pos, const void *buf,
size_t count);
static ssize_t zero_read(chardev_t *dev, size_t pos, void *buf, size_t count);
static long zero_mmap(vnode_t *file, mobj_t **ret);
chardev_ops_t null_dev_ops = {.read = null_read,
.write = null_write,
.mmap = NULL,
.fill_pframe = NULL,
.flush_pframe = NULL};
chardev_ops_t zero_dev_ops = {.read = zero_read,
.write = null_write,
.mmap = zero_mmap,
.fill_pframe = NULL,
.flush_pframe = NULL};
/**
* The char device code needs to know about these mem devices, so create
* chardev_t's for null and zero, fill them in, and register them.
*
* Use kmalloc, MEM_NULL_DEVID, MEM_ZERO_DEVID, and chardev_register.
* See dev.h for device ids to use with MKDEVID.
*/
void memdevs_init()
{
// NOT_YET_IMPLEMENTED("DRIVERS: memdevs_init");
// create chardev_t's for null and zero
chardev_t *null_dev = kmalloc(sizeof(chardev_t));
if (null_dev == NULL)
{
dbg(DBG_DISK, "ERROR: kmalloc failed on null_dev in memdevs_init\n");
return;
}
chardev_t *zero_dev = kmalloc(sizeof(chardev_t));
if (zero_dev == NULL)
{
dbg(DBG_DISK, "ERROR: kmalloc failed on zero_dev in memdevs_init\n");
return;
}
// fill them in
null_dev->cd_id = MEM_NULL_DEVID;
null_dev->cd_ops = &null_dev_ops;
zero_dev->cd_id = MEM_ZERO_DEVID;
zero_dev->cd_ops = &zero_dev_ops;
// register them
chardev_register(null_dev);
chardev_register(zero_dev);
}
/**
* Reads a given number of bytes from the null device into a
* buffer. Any read performed on the null device should read 0 bytes.
*
* @param dev the null device
* @param pos the offset to read from; should be ignored
* @param buf the buffer to read into
* @param count the maximum number of bytes to read
* @return the number of bytes read, which should be 0
*/
static ssize_t null_read(chardev_t *dev, size_t pos, void *buf, size_t count)
{
// NOT_YET_IMPLEMENTED("DRIVERS: null_read");
// TODO: ask about buffer checking
return 0; // return reading no bytes
}
/**
* Writes a given number of bytes to the null device from a
* buffer. Writing to the null device should _ALWAYS_ be successful
* and write the maximum number of bytes.
*
* @param dev the null device
* @param pos offset the offset to write to; should be ignored
* @param buf buffer to read from
* @param count the maximum number of bytes to write
* @return the number of bytes written, which should be `count`
*/
static ssize_t null_write(chardev_t *dev, size_t pos, const void *buf,
size_t count)
{
// NOT_YET_IMPLEMENTED("DRIVERS: null_write");
// check if the buffer is NULL
if (buf == NULL)
{
return -EINVAL;
}
// there is no true writing, so just do nothing here
// return the number of bytes written
return count;
}
/**
* Reads a given number of bytes from the zero device into a
* buffer. Any read from the zero device should be a series of zeros.
*
* @param dev the zero device
* @param pos the offset to start reading from; should be ignored
* @param buf the buffer to write to
* @param count the maximum number of bytes to read
* @return the number of bytes read. Hint: should always read the maximum
* number of bytes
*/
static ssize_t zero_read(chardev_t *dev, size_t pos, void *buf, size_t count)
{
// NOT_YET_IMPLEMENTED("DRIVERS: zero_read");
// check if the buffer is NULL
if (buf == NULL)
{
return -EINVAL;
}
// fill the buffer with zeros
memset(buf, 0, count);
// return the number of bytes read
return count;
}
/**
* Unlike in s5fs_mmap(), you can't necessarily use the file's underlying mobj.
* Instead, you should simply provide an anonymous object to ret.
*/
static long zero_mmap(vnode_t *file, mobj_t **ret)
{
// NOT_YET_IMPLEMENTED("VM: zero_mmap");
// create a new anonymous object
mobj_t *mobj = anon_create();
mobj_unlock(mobj); // unlock the object from the init
if (mobj == NULL)
{
return -ENOMEM;
}
// set the return value
*ret = mobj;
return 0;
}
|