00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <types.h>
00037 #include <kern/errno.h>
00038 #include <kern/fcntl.h>
00039 #include <stat.h>
00040 #include <lib.h>
00041 #include <uio.h>
00042 #include <synch.h>
00043 #include <vnode.h>
00044 #include <device.h>
00045
00046
00047
00048
00049
00050
00051 static
00052 int
00053 dev_open(struct vnode *v, int flags)
00054 {
00055 struct device *d = v->vn_data;
00056
00057 if (flags & (O_CREAT | O_TRUNC | O_EXCL | O_APPEND)) {
00058 return EINVAL;
00059 }
00060
00061 return d->d_open(d, flags);
00062 }
00063
00064
00065
00066
00067
00068 static
00069 int
00070 dev_close(struct vnode *v)
00071 {
00072 struct device *d = v->vn_data;
00073 return d->d_close(d);
00074 }
00075
00076
00077
00078
00079
00080 static
00081 int
00082 dev_reclaim(struct vnode *v)
00083 {
00084 (void)v;
00085
00086 return 0;
00087 }
00088
00089
00090
00091
00092 static
00093 int
00094 dev_read(struct vnode *v, struct uio *uio)
00095 {
00096 struct device *d = v->vn_data;
00097 KASSERT(uio->uio_rw == UIO_READ);
00098 return d->d_io(d, uio);
00099 }
00100
00101
00102
00103
00104
00105 static
00106 int
00107 null_io(struct vnode *v, struct uio *uio)
00108 {
00109 (void)v;
00110 (void)uio;
00111 return EINVAL;
00112 }
00113
00114
00115
00116
00117 static
00118 int
00119 dev_write(struct vnode *v, struct uio *uio)
00120 {
00121 struct device *d = v->vn_data;
00122 KASSERT(uio->uio_rw == UIO_WRITE);
00123 return d->d_io(d, uio);
00124 }
00125
00126
00127
00128
00129 static
00130 int
00131 dev_ioctl(struct vnode *v, int op, userptr_t data)
00132 {
00133 struct device *d = v->vn_data;
00134 return d->d_ioctl(d, op, data);
00135 }
00136
00137
00138
00139
00140
00141
00142 static
00143 int
00144 dev_stat(struct vnode *v, struct stat *statbuf)
00145 {
00146 struct device *d = v->vn_data;
00147 int result;
00148
00149 bzero(statbuf, sizeof(struct stat));
00150
00151 if (d->d_blocks > 0) {
00152 statbuf->st_size = d->d_blocks * d->d_blocksize;
00153 statbuf->st_blksize = d->d_blocksize;
00154 }
00155 else {
00156 statbuf->st_size = 0;
00157 }
00158
00159 result = VOP_GETTYPE(v, &statbuf->st_mode);
00160 if (result) {
00161 return result;
00162 }
00163
00164 statbuf->st_mode |= 0600;
00165
00166 statbuf->st_nlink = 1;
00167 statbuf->st_blocks = d->d_blocks;
00168
00169
00170 statbuf->st_dev = 0;
00171
00172
00173 statbuf->st_rdev = d->d_devnumber;
00174
00175 return 0;
00176 }
00177
00178
00179
00180
00181
00182
00183 static
00184 int
00185 dev_gettype(struct vnode *v, mode_t *ret)
00186 {
00187 struct device *d = v->vn_data;
00188 if (d->d_blocks > 0) {
00189 *ret = S_IFBLK;
00190 }
00191 else {
00192 *ret = S_IFCHR;
00193 }
00194 return 0;
00195 }
00196
00197
00198
00199
00200
00201
00202 static
00203 int
00204 dev_tryseek(struct vnode *v, off_t pos)
00205 {
00206 struct device *d = v->vn_data;
00207 if (d->d_blocks > 0) {
00208 if ((pos % d->d_blocksize)!=0) {
00209
00210 return EINVAL;
00211 }
00212 if (pos < 0) {
00213
00214
00215
00216
00217
00218
00219 return EINVAL;
00220 }
00221 if (pos / d->d_blocksize >= d->d_blocks) {
00222
00223 return EINVAL;
00224 }
00225 }
00226 else {
00227 return ESPIPE;
00228 }
00229 return 0;
00230 }
00231
00232
00233
00234
00235 static
00236 int
00237 null_fsync(struct vnode *v)
00238 {
00239 (void)v;
00240 return 0;
00241 }
00242
00243
00244
00245
00246
00247 static
00248 int
00249 dev_mmap(struct vnode *v )
00250 {
00251 (void)v;
00252 return EUNIMP;
00253 }
00254
00255
00256
00257
00258 static
00259 int
00260 dev_truncate(struct vnode *v, off_t len)
00261 {
00262 struct device *d = v->vn_data;
00263
00264
00265
00266
00267 if (d->d_blocks > 0 && (off_t)(d->d_blocks*d->d_blocksize) == len) {
00268 return 0;
00269 }
00270
00271 return EINVAL;
00272 }
00273
00274
00275
00276
00277
00278
00279
00280 static
00281 int
00282 dev_namefile(struct vnode *v, struct uio *uio)
00283 {
00284
00285
00286
00287
00288
00289
00290 (void)v;
00291 (void)uio;
00292
00293 return 0;
00294 }
00295
00296
00297
00298
00299
00300 static
00301 int
00302 null_creat(struct vnode *v, const char *name, bool excl, mode_t mode,
00303 struct vnode **result)
00304 {
00305 (void)v;
00306 (void)name;
00307 (void)excl;
00308 (void)mode;
00309 (void)result;
00310 return ENOTDIR;
00311 }
00312
00313 static
00314 int
00315 null_mkdir(struct vnode *v, const char *name, mode_t mode)
00316 {
00317 (void)v;
00318 (void)name;
00319 (void)mode;
00320 return ENOTDIR;
00321 }
00322
00323 static
00324 int
00325 null_symlink(struct vnode *v, const char *contents, const char *name)
00326 {
00327 (void)v;
00328 (void)contents;
00329 (void)name;
00330 return ENOTDIR;
00331 }
00332
00333 static
00334 int
00335 null_nameop(struct vnode *v, const char *name)
00336 {
00337 (void)v;
00338 (void)name;
00339 return ENOTDIR;
00340 }
00341
00342 static
00343 int
00344 null_link(struct vnode *v, const char *name, struct vnode *file)
00345 {
00346 (void)v;
00347 (void)name;
00348 (void)file;
00349 return ENOTDIR;
00350 }
00351
00352 static
00353 int
00354 null_rename(struct vnode *v, const char *n1, struct vnode *v2, const char *n2)
00355 {
00356 (void)v;
00357 (void)n1;
00358 (void)v2;
00359 (void)n2;
00360 return ENOTDIR;
00361 }
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 static
00377 int
00378 dev_lookup(struct vnode *dir,
00379 char *pathname, struct vnode **result)
00380 {
00381
00382
00383
00384
00385
00386 if (strlen(pathname)>0) {
00387 return ENOENT;
00388 }
00389 VOP_INCREF(dir);
00390 *result = dir;
00391 return 0;
00392 }
00393
00394 static
00395 int
00396 dev_lookparent(struct vnode *dir,
00397 char *pathname, struct vnode **result,
00398 char *namebuf, size_t buflen)
00399 {
00400
00401
00402
00403 (void)dir;
00404 (void)pathname;
00405 (void)result;
00406 (void)namebuf;
00407 (void)buflen;
00408
00409 return ENOTDIR;
00410 }
00411
00412
00413
00414
00415 static const struct vnode_ops dev_vnode_ops = {
00416 VOP_MAGIC,
00417
00418 dev_open,
00419 dev_close,
00420 dev_reclaim,
00421 dev_read,
00422 null_io,
00423 null_io,
00424 dev_write,
00425 dev_ioctl,
00426 dev_stat,
00427 dev_gettype,
00428 dev_tryseek,
00429 null_fsync,
00430 dev_mmap,
00431 dev_truncate,
00432 dev_namefile,
00433 null_creat,
00434 null_symlink,
00435 null_mkdir,
00436 null_link,
00437 null_nameop,
00438 null_nameop,
00439 null_rename,
00440 dev_lookup,
00441 dev_lookparent,
00442 };
00443
00444
00445
00446
00447 struct vnode *
00448 dev_create_vnode(struct device *dev)
00449 {
00450 int result;
00451 struct vnode *v;
00452
00453 v = kmalloc(sizeof(struct vnode));
00454 if (v==NULL) {
00455 return NULL;
00456 }
00457
00458 result = VOP_INIT(v, &dev_vnode_ops, NULL, dev);
00459 if (result != 0) {
00460 panic("While creating vnode for device: VOP_INIT: %s\n",
00461 strerror(result));
00462 }
00463
00464 return v;
00465 }