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
00037
00038
00039
00040
00041
00042
00043 #include <types.h>
00044 #include <kern/errno.h>
00045 #include <kern/fcntl.h>
00046 #include <stat.h>
00047 #include <lib.h>
00048 #include <array.h>
00049 #include <uio.h>
00050 #include <synch.h>
00051 #include <lamebus/emu.h>
00052 #include <platform/bus.h>
00053 #include <vfs.h>
00054 #include <emufs.h>
00055 #include "autoconf.h"
00056
00057
00058 #define REG_HANDLE 0
00059 #define REG_OFFSET 4
00060 #define REG_IOLEN 8
00061 #define REG_OPER 12
00062 #define REG_RESULT 16
00063
00064
00065 #define EMU_BUFFER 32768
00066
00067
00068 #define EMU_OP_OPEN 1
00069 #define EMU_OP_CREATE 2
00070 #define EMU_OP_EXCLCREATE 3
00071 #define EMU_OP_CLOSE 4
00072 #define EMU_OP_READ 5
00073 #define EMU_OP_READDIR 6
00074 #define EMU_OP_WRITE 7
00075 #define EMU_OP_GETSIZE 8
00076 #define EMU_OP_TRUNC 9
00077
00078
00079 #define EMU_RES_SUCCESS 1
00080 #define EMU_RES_BADHANDLE 2
00081 #define EMU_RES_BADOP 3
00082 #define EMU_RES_BADPATH 4
00083 #define EMU_RES_BADSIZE 5
00084 #define EMU_RES_EXISTS 6
00085 #define EMU_RES_ISDIR 7
00086 #define EMU_RES_MEDIA 8
00087 #define EMU_RES_NOHANDLES 9
00088 #define EMU_RES_NOSPACE 10
00089 #define EMU_RES_NOTDIR 11
00090 #define EMU_RES_UNKNOWN 12
00091 #define EMU_RES_UNSUPP 13
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 static
00102 inline
00103 uint32_t
00104 emu_rreg(struct emu_softc *sc, uint32_t reg)
00105 {
00106 return bus_read_register(sc->e_busdata, sc->e_buspos, reg);
00107 }
00108
00109
00110
00111
00112 static
00113 inline
00114 void
00115 emu_wreg(struct emu_softc *sc, uint32_t reg, uint32_t val)
00116 {
00117 bus_write_register(sc->e_busdata, sc->e_buspos, reg, val);
00118 }
00119
00120
00121
00122
00123 void
00124 emu_irq(void *dev)
00125 {
00126 struct emu_softc *sc = dev;
00127
00128 sc->e_result = emu_rreg(sc, REG_RESULT);
00129 emu_wreg(sc, REG_RESULT, 0);
00130
00131 V(sc->e_sem);
00132 }
00133
00134
00135
00136
00137
00138 static
00139 uint32_t
00140 translate_err(struct emu_softc *sc, uint32_t code)
00141 {
00142 switch (code) {
00143 case EMU_RES_SUCCESS: return 0;
00144 case EMU_RES_BADHANDLE:
00145 case EMU_RES_BADOP:
00146 case EMU_RES_BADSIZE:
00147 panic("emu%d: got fatal result code %d\n", sc->e_unit, code);
00148 case EMU_RES_BADPATH: return ENOENT;
00149 case EMU_RES_EXISTS: return EEXIST;
00150 case EMU_RES_ISDIR: return EISDIR;
00151 case EMU_RES_MEDIA: return EIO;
00152 case EMU_RES_NOHANDLES: return ENFILE;
00153 case EMU_RES_NOSPACE: return ENOSPC;
00154 case EMU_RES_NOTDIR: return ENOTDIR;
00155 case EMU_RES_UNKNOWN: return EIO;
00156 case EMU_RES_UNSUPP: return EUNIMP;
00157 }
00158 kprintf("emu%d: Unknown result code %d\n", sc->e_unit, code);
00159 return EAGAIN;
00160 }
00161
00162
00163
00164
00165 static
00166 int
00167 emu_waitdone(struct emu_softc *sc)
00168 {
00169 P(sc->e_sem);
00170 return translate_err(sc, sc->e_result);
00171 }
00172
00173
00174
00175
00176
00177
00178
00179 static
00180 int
00181 emu_open(struct emu_softc *sc, uint32_t handle, const char *name,
00182 bool create, bool excl, mode_t mode,
00183 uint32_t *newhandle, int *newisdir)
00184 {
00185 uint32_t op;
00186 int result;
00187
00188 if (strlen(name)+1 > EMU_MAXIO) {
00189 return ENAMETOOLONG;
00190 }
00191
00192 if (create && excl) {
00193 op = EMU_OP_EXCLCREATE;
00194 }
00195 else if (create) {
00196 op = EMU_OP_CREATE;
00197 }
00198 else {
00199 op = EMU_OP_OPEN;
00200 }
00201
00202
00203 (void)mode;
00204
00205 lock_acquire(sc->e_lock);
00206
00207 strcpy(sc->e_iobuf, name);
00208 emu_wreg(sc, REG_IOLEN, strlen(name));
00209 emu_wreg(sc, REG_HANDLE, handle);
00210 emu_wreg(sc, REG_OPER, op);
00211 result = emu_waitdone(sc);
00212
00213 if (result==0) {
00214 *newhandle = emu_rreg(sc, REG_HANDLE);
00215 *newisdir = emu_rreg(sc, REG_IOLEN)>0;
00216 }
00217
00218 lock_release(sc->e_lock);
00219 return result;
00220 }
00221
00222
00223
00224
00225
00226
00227 static
00228 int
00229 emu_close(struct emu_softc *sc, uint32_t handle)
00230 {
00231 int result;
00232 bool mine;
00233 int retries = 0;
00234
00235 mine = lock_do_i_hold(sc->e_lock);
00236 if (!mine) {
00237 lock_acquire(sc->e_lock);
00238 }
00239
00240 while (1) {
00241
00242
00243 emu_wreg(sc, REG_HANDLE, handle);
00244 emu_wreg(sc, REG_OPER, EMU_OP_CLOSE);
00245 result = emu_waitdone(sc);
00246
00247 if (result==EIO && retries < 10) {
00248 kprintf("emu%d: I/O error on close, retrying\n",
00249 sc->e_unit);
00250 retries++;
00251 continue;
00252 }
00253 break;
00254 }
00255
00256 if (!mine) {
00257 lock_release(sc->e_lock);
00258 }
00259 return result;
00260 }
00261
00262
00263
00264
00265 static
00266 int
00267 emu_doread(struct emu_softc *sc, uint32_t handle, uint32_t len,
00268 uint32_t op, struct uio *uio)
00269 {
00270 int result;
00271
00272 KASSERT(uio->uio_rw == UIO_READ);
00273
00274 lock_acquire(sc->e_lock);
00275
00276 emu_wreg(sc, REG_HANDLE, handle);
00277 emu_wreg(sc, REG_IOLEN, len);
00278 emu_wreg(sc, REG_OFFSET, uio->uio_offset);
00279 emu_wreg(sc, REG_OPER, op);
00280 result = emu_waitdone(sc);
00281 if (result) {
00282 goto out;
00283 }
00284
00285 result = uiomove(sc->e_iobuf, emu_rreg(sc, REG_IOLEN), uio);
00286
00287 uio->uio_offset = emu_rreg(sc, REG_OFFSET);
00288
00289 out:
00290 lock_release(sc->e_lock);
00291 return result;
00292 }
00293
00294
00295
00296
00297 static
00298 int
00299 emu_read(struct emu_softc *sc, uint32_t handle, uint32_t len,
00300 struct uio *uio)
00301 {
00302 return emu_doread(sc, handle, len, EMU_OP_READ, uio);
00303 }
00304
00305
00306
00307
00308 static
00309 int
00310 emu_readdir(struct emu_softc *sc, uint32_t handle, uint32_t len,
00311 struct uio *uio)
00312 {
00313 return emu_doread(sc, handle, len, EMU_OP_READDIR, uio);
00314 }
00315
00316
00317
00318
00319 static
00320 int
00321 emu_write(struct emu_softc *sc, uint32_t handle, uint32_t len,
00322 struct uio *uio)
00323 {
00324 int result;
00325
00326 KASSERT(uio->uio_rw == UIO_WRITE);
00327
00328 lock_acquire(sc->e_lock);
00329
00330 emu_wreg(sc, REG_HANDLE, handle);
00331 emu_wreg(sc, REG_IOLEN, len);
00332 emu_wreg(sc, REG_OFFSET, uio->uio_offset);
00333
00334 result = uiomove(sc->e_iobuf, len, uio);
00335 if (result) {
00336 goto out;
00337 }
00338
00339 emu_wreg(sc, REG_OPER, EMU_OP_WRITE);
00340 result = emu_waitdone(sc);
00341
00342 out:
00343 lock_release(sc->e_lock);
00344 return result;
00345 }
00346
00347
00348
00349
00350 static
00351 int
00352 emu_getsize(struct emu_softc *sc, uint32_t handle, off_t *retval)
00353 {
00354 int result;
00355
00356 lock_acquire(sc->e_lock);
00357
00358 emu_wreg(sc, REG_HANDLE, handle);
00359 emu_wreg(sc, REG_OPER, EMU_OP_GETSIZE);
00360 result = emu_waitdone(sc);
00361 if (result==0) {
00362 *retval = emu_rreg(sc, REG_IOLEN);
00363 }
00364
00365 lock_release(sc->e_lock);
00366 return result;
00367 }
00368
00369
00370
00371
00372 static
00373 int
00374 emu_trunc(struct emu_softc *sc, uint32_t handle, off_t len)
00375 {
00376 int result;
00377
00378 lock_acquire(sc->e_lock);
00379
00380 emu_wreg(sc, REG_HANDLE, handle);
00381 emu_wreg(sc, REG_IOLEN, len);
00382 emu_wreg(sc, REG_OPER, EMU_OP_TRUNC);
00383 result = emu_waitdone(sc);
00384
00385 lock_release(sc->e_lock);
00386 return result;
00387 }
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399 static int emufs_loadvnode(struct emufs_fs *ef, uint32_t handle, int isdir,
00400 struct emufs_vnode **ret);
00401
00402
00403
00404
00405 static
00406 int
00407 emufs_open(struct vnode *v, int openflags)
00408 {
00409
00410
00411
00412
00413
00414
00415
00416
00417 if (openflags & O_APPEND) {
00418 return EUNIMP;
00419 }
00420
00421 (void)v;
00422
00423 return 0;
00424 }
00425
00426
00427
00428
00429 static
00430 int
00431 emufs_opendir(struct vnode *v, int openflags)
00432 {
00433 switch (openflags & O_ACCMODE) {
00434 case O_RDONLY:
00435 break;
00436 case O_WRONLY:
00437 case O_RDWR:
00438 default:
00439 return EISDIR;
00440 }
00441 if (openflags & O_APPEND) {
00442 return EISDIR;
00443 }
00444
00445 (void)v;
00446 return 0;
00447 }
00448
00449
00450
00451
00452 static
00453 int
00454 emufs_close(struct vnode *v)
00455 {
00456 (void)v;
00457 return 0;
00458 }
00459
00460
00461
00462
00463
00464
00465 static
00466 int
00467 emufs_reclaim(struct vnode *v)
00468 {
00469 struct emufs_vnode *ev = v->vn_data;
00470 struct emufs_fs *ef = v->vn_fs->fs_data;
00471 unsigned ix, i, num;
00472 int result;
00473
00474
00475
00476
00477
00478
00479 vfs_biglock_acquire();
00480 lock_acquire(ef->ef_emu->e_lock);
00481
00482 if (ev->ev_v.vn_refcount != 1) {
00483 lock_release(ef->ef_emu->e_lock);
00484 vfs_biglock_release();
00485 return EBUSY;
00486 }
00487
00488
00489 result = emu_close(ev->ev_emu, ev->ev_handle);
00490 if (result) {
00491 lock_release(ef->ef_emu->e_lock);
00492 vfs_biglock_release();
00493 return result;
00494 }
00495
00496 num = vnodearray_num(ef->ef_vnodes);
00497 ix = num;
00498 for (i=0; i<num; i++) {
00499 struct vnode *vx;
00500
00501 vx = vnodearray_get(ef->ef_vnodes, i);
00502 if (vx == v) {
00503 ix = i;
00504 break;
00505 }
00506 }
00507 if (ix == num) {
00508 panic("emu%d: reclaim vnode %u not in vnode pool\n",
00509 ef->ef_emu->e_unit, ev->ev_handle);
00510 }
00511
00512 vnodearray_remove(ef->ef_vnodes, ix);
00513 VOP_CLEANUP(&ev->ev_v);
00514
00515 lock_release(ef->ef_emu->e_lock);
00516 vfs_biglock_release();
00517
00518 kfree(ev);
00519 return 0;
00520 }
00521
00522
00523
00524
00525 static
00526 int
00527 emufs_read(struct vnode *v, struct uio *uio)
00528 {
00529 struct emufs_vnode *ev = v->vn_data;
00530 uint32_t amt;
00531 size_t oldresid;
00532 int result;
00533
00534 KASSERT(uio->uio_rw==UIO_READ);
00535
00536 while (uio->uio_resid > 0) {
00537 amt = uio->uio_resid;
00538 if (amt > EMU_MAXIO) {
00539 amt = EMU_MAXIO;
00540 }
00541
00542 oldresid = uio->uio_resid;
00543
00544 result = emu_read(ev->ev_emu, ev->ev_handle, amt, uio);
00545 if (result) {
00546 return result;
00547 }
00548
00549 if (uio->uio_resid == oldresid) {
00550
00551 break;
00552 }
00553 }
00554
00555 return 0;
00556 }
00557
00558
00559
00560
00561 static
00562 int
00563 emufs_getdirentry(struct vnode *v, struct uio *uio)
00564 {
00565 struct emufs_vnode *ev = v->vn_data;
00566 uint32_t amt;
00567
00568 KASSERT(uio->uio_rw==UIO_READ);
00569
00570 amt = uio->uio_resid;
00571 if (amt > EMU_MAXIO) {
00572 amt = EMU_MAXIO;
00573 }
00574
00575 return emu_readdir(ev->ev_emu, ev->ev_handle, amt, uio);
00576 }
00577
00578
00579
00580
00581 static
00582 int
00583 emufs_write(struct vnode *v, struct uio *uio)
00584 {
00585 struct emufs_vnode *ev = v->vn_data;
00586 uint32_t amt;
00587 size_t oldresid;
00588 int result;
00589
00590 KASSERT(uio->uio_rw==UIO_WRITE);
00591
00592 while (uio->uio_resid > 0) {
00593 amt = uio->uio_resid;
00594 if (amt > EMU_MAXIO) {
00595 amt = EMU_MAXIO;
00596 }
00597
00598 oldresid = uio->uio_resid;
00599
00600 result = emu_write(ev->ev_emu, ev->ev_handle, amt, uio);
00601 if (result) {
00602 return result;
00603 }
00604
00605 if (uio->uio_resid == oldresid) {
00606
00607 break;
00608 }
00609 }
00610
00611 return 0;
00612 }
00613
00614
00615
00616
00617 static
00618 int
00619 emufs_ioctl(struct vnode *v, int op, userptr_t data)
00620 {
00621
00622
00623
00624
00625 (void)v;
00626 (void)op;
00627 (void)data;
00628
00629 return EINVAL;
00630 }
00631
00632
00633
00634
00635 static
00636 int
00637 emufs_stat(struct vnode *v, struct stat *statbuf)
00638 {
00639 struct emufs_vnode *ev = v->vn_data;
00640 int result;
00641
00642 bzero(statbuf, sizeof(struct stat));
00643
00644 result = emu_getsize(ev->ev_emu, ev->ev_handle, &statbuf->st_size);
00645 if (result) {
00646 return result;
00647 }
00648
00649 result = VOP_GETTYPE(v, &statbuf->st_mode);
00650 if (result) {
00651 return result;
00652 }
00653 statbuf->st_mode |= 0644;
00654 statbuf->st_nlink = 1;
00655 statbuf->st_blocks = 0;
00656
00657 return 0;
00658 }
00659
00660
00661
00662
00663 static
00664 int
00665 emufs_file_gettype(struct vnode *v, uint32_t *result)
00666 {
00667 (void)v;
00668 *result = S_IFREG;
00669 return 0;
00670 }
00671
00672
00673
00674
00675 static
00676 int
00677 emufs_dir_gettype(struct vnode *v, uint32_t *result)
00678 {
00679 (void)v;
00680 *result = S_IFDIR;
00681 return 0;
00682 }
00683
00684
00685
00686
00687 static
00688 int
00689 emufs_tryseek(struct vnode *v, off_t pos)
00690 {
00691 if (pos<0) {
00692 return EINVAL;
00693 }
00694
00695
00696 (void)v;
00697
00698 return 0;
00699 }
00700
00701
00702
00703
00704 static
00705 int
00706 emufs_fsync(struct vnode *v)
00707 {
00708 (void)v;
00709 return 0;
00710 }
00711
00712
00713
00714
00715 static
00716 int
00717 emufs_truncate(struct vnode *v, off_t len)
00718 {
00719 struct emufs_vnode *ev = v->vn_data;
00720 return emu_trunc(ev->ev_emu, ev->ev_handle, len);
00721 }
00722
00723
00724
00725
00726 static
00727 int
00728 emufs_creat(struct vnode *dir, const char *name, bool excl, mode_t mode,
00729 struct vnode **ret)
00730 {
00731 struct emufs_vnode *ev = dir->vn_data;
00732 struct emufs_fs *ef = dir->vn_fs->fs_data;
00733 struct emufs_vnode *newguy;
00734 uint32_t handle;
00735 int result;
00736 int isdir;
00737
00738 result = emu_open(ev->ev_emu, ev->ev_handle, name, true, excl, mode,
00739 &handle, &isdir);
00740 if (result) {
00741 return result;
00742 }
00743
00744 result = emufs_loadvnode(ef, handle, isdir, &newguy);
00745 if (result) {
00746 emu_close(ev->ev_emu, handle);
00747 return result;
00748 }
00749
00750 *ret = &newguy->ev_v;
00751 return 0;
00752 }
00753
00754
00755
00756
00757 static
00758 int
00759 emufs_lookup(struct vnode *dir, char *pathname, struct vnode **ret)
00760 {
00761 struct emufs_vnode *ev = dir->vn_data;
00762 struct emufs_fs *ef = dir->vn_fs->fs_data;
00763 struct emufs_vnode *newguy;
00764 uint32_t handle;
00765 int result;
00766 int isdir;
00767
00768 result = emu_open(ev->ev_emu, ev->ev_handle, pathname, false, false, 0,
00769 &handle, &isdir);
00770 if (result) {
00771 return result;
00772 }
00773
00774 result = emufs_loadvnode(ef, handle, isdir, &newguy);
00775 if (result) {
00776 emu_close(ev->ev_emu, handle);
00777 return result;
00778 }
00779
00780 *ret = &newguy->ev_v;
00781 return 0;
00782 }
00783
00784
00785
00786
00787 static
00788 int
00789 emufs_lookparent(struct vnode *dir, char *pathname, struct vnode **ret,
00790 char *buf, size_t len)
00791 {
00792 char *s;
00793
00794 s = strrchr(pathname, '/');
00795 if (s==NULL) {
00796
00797 if (strlen(pathname)+1 > len) {
00798 return ENAMETOOLONG;
00799 }
00800 VOP_INCREF(dir);
00801 *ret = dir;
00802 strcpy(buf, pathname);
00803 return 0;
00804 }
00805
00806 *s = 0;
00807 s++;
00808 if (strlen(s)+1 > len) {
00809 return ENAMETOOLONG;
00810 }
00811 strcpy(buf, s);
00812
00813 return emufs_lookup(dir, pathname, ret);
00814 }
00815
00816
00817
00818
00819 static
00820 int
00821 emufs_namefile(struct vnode *v, struct uio *uio)
00822 {
00823 struct emufs_vnode *ev = v->vn_data;
00824 struct emufs_fs *ef = v->vn_fs->fs_data;
00825
00826 if (ev == ef->ef_root) {
00827
00828
00829
00830 return 0;
00831 }
00832
00833 (void)uio;
00834
00835 return EUNIMP;
00836 }
00837
00838
00839
00840
00841 static
00842 int
00843 emufs_mmap(struct vnode *v)
00844 {
00845 (void)v;
00846 return EUNIMP;
00847 }
00848
00849
00850
00851
00852
00853
00854
00855 static
00856 int
00857 emufs_dir_tryseek(struct vnode *v, off_t pos)
00858 {
00859 (void)v;
00860 (void)pos;
00861 return EUNIMP;
00862 }
00863
00864 static
00865 int
00866 emufs_symlink(struct vnode *v, const char *contents, const char *name)
00867 {
00868 (void)v;
00869 (void)contents;
00870 (void)name;
00871 return EUNIMP;
00872 }
00873
00874 static
00875 int
00876 emufs_mkdir(struct vnode *v, const char *name, mode_t mode)
00877 {
00878 (void)v;
00879 (void)name;
00880 (void)mode;
00881 return EUNIMP;
00882 }
00883
00884 static
00885 int
00886 emufs_link(struct vnode *v, const char *name, struct vnode *target)
00887 {
00888 (void)v;
00889 (void)name;
00890 (void)target;
00891 return EUNIMP;
00892 }
00893
00894 static
00895 int
00896 emufs_remove(struct vnode *v, const char *name)
00897 {
00898 (void)v;
00899 (void)name;
00900 return EUNIMP;
00901 }
00902
00903 static
00904 int
00905 emufs_rmdir(struct vnode *v, const char *name)
00906 {
00907 (void)v;
00908 (void)name;
00909 return EUNIMP;
00910 }
00911
00912 static
00913 int
00914 emufs_rename(struct vnode *v1, const char *n1,
00915 struct vnode *v2, const char *n2)
00916 {
00917 (void)v1;
00918 (void)n1;
00919 (void)v2;
00920 (void)n2;
00921 return EUNIMP;
00922 }
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939 static
00940 int
00941 emufs_void_op_isdir(struct vnode *v)
00942 {
00943 (void)v;
00944 return EISDIR;
00945 }
00946
00947 static
00948 int
00949 emufs_uio_op_isdir(struct vnode *v, struct uio *uio)
00950 {
00951 (void)v;
00952 (void)uio;
00953 return EISDIR;
00954 }
00955
00956 static
00957 int
00958 emufs_uio_op_notdir(struct vnode *v, struct uio *uio)
00959 {
00960 (void)v;
00961 (void)uio;
00962 return ENOTDIR;
00963 }
00964
00965 static
00966 int
00967 emufs_name_op_notdir(struct vnode *v, const char *name)
00968 {
00969 (void)v;
00970 (void)name;
00971 return ENOTDIR;
00972 }
00973
00974 static
00975 int
00976 emufs_readlink_notlink(struct vnode *v, struct uio *uio)
00977 {
00978 (void)v;
00979 (void)uio;
00980 return EINVAL;
00981 }
00982
00983 static
00984 int
00985 emufs_creat_notdir(struct vnode *v, const char *name, bool excl, mode_t mode,
00986 struct vnode **retval)
00987 {
00988 (void)v;
00989 (void)name;
00990 (void)excl;
00991 (void)mode;
00992 (void)retval;
00993 return ENOTDIR;
00994 }
00995
00996 static
00997 int
00998 emufs_symlink_notdir(struct vnode *v, const char *contents, const char *name)
00999 {
01000 (void)v;
01001 (void)contents;
01002 (void)name;
01003 return ENOTDIR;
01004 }
01005
01006 static
01007 int
01008 emufs_mkdir_notdir(struct vnode *v, const char *name, mode_t mode)
01009 {
01010 (void)v;
01011 (void)name;
01012 (void)mode;
01013 return ENOTDIR;
01014 }
01015
01016 static
01017 int
01018 emufs_link_notdir(struct vnode *v, const char *name, struct vnode *target)
01019 {
01020 (void)v;
01021 (void)name;
01022 (void)target;
01023 return ENOTDIR;
01024 }
01025
01026 static
01027 int
01028 emufs_rename_notdir(struct vnode *v1, const char *n1,
01029 struct vnode *v2, const char *n2)
01030 {
01031 (void)v1;
01032 (void)n1;
01033 (void)v2;
01034 (void)n2;
01035 return ENOTDIR;
01036 }
01037
01038 static
01039 int
01040 emufs_lookup_notdir(struct vnode *v, char *pathname, struct vnode **result)
01041 {
01042 (void)v;
01043 (void)pathname;
01044 (void)result;
01045 return ENOTDIR;
01046 }
01047
01048 static
01049 int
01050 emufs_lookparent_notdir(struct vnode *v, char *pathname, struct vnode **result,
01051 char *buf, size_t len)
01052 {
01053 (void)v;
01054 (void)pathname;
01055 (void)result;
01056 (void)buf;
01057 (void)len;
01058 return ENOTDIR;
01059 }
01060
01061
01062 static
01063 int
01064 emufs_truncate_isdir(struct vnode *v, off_t len)
01065 {
01066 (void)v;
01067 (void)len;
01068 return ENOTDIR;
01069 }
01070
01071
01072
01073
01074
01075
01076 static const struct vnode_ops emufs_fileops = {
01077 VOP_MAGIC,
01078
01079 emufs_open,
01080 emufs_close,
01081 emufs_reclaim,
01082
01083 emufs_read,
01084 emufs_readlink_notlink,
01085 emufs_uio_op_notdir,
01086 emufs_write,
01087 emufs_ioctl,
01088 emufs_stat,
01089 emufs_file_gettype,
01090 emufs_tryseek,
01091 emufs_fsync,
01092 emufs_mmap,
01093 emufs_truncate,
01094 emufs_uio_op_notdir,
01095
01096 emufs_creat_notdir,
01097 emufs_symlink_notdir,
01098 emufs_mkdir_notdir,
01099 emufs_link_notdir,
01100 emufs_name_op_notdir,
01101 emufs_name_op_notdir,
01102 emufs_rename_notdir,
01103
01104 emufs_lookup_notdir,
01105 emufs_lookparent_notdir,
01106 };
01107
01108
01109
01110
01111 static const struct vnode_ops emufs_dirops = {
01112 VOP_MAGIC,
01113
01114 emufs_opendir,
01115 emufs_close,
01116 emufs_reclaim,
01117
01118 emufs_uio_op_isdir,
01119 emufs_uio_op_isdir,
01120 emufs_getdirentry,
01121 emufs_uio_op_isdir,
01122 emufs_ioctl,
01123 emufs_stat,
01124 emufs_dir_gettype,
01125 emufs_dir_tryseek,
01126 emufs_void_op_isdir,
01127 emufs_void_op_isdir,
01128 emufs_truncate_isdir,
01129 emufs_namefile,
01130
01131 emufs_creat,
01132 emufs_symlink,
01133 emufs_mkdir,
01134 emufs_link,
01135 emufs_remove,
01136 emufs_rmdir,
01137 emufs_rename,
01138
01139 emufs_lookup,
01140 emufs_lookparent,
01141 };
01142
01143
01144
01145
01146 static
01147 int
01148 emufs_loadvnode(struct emufs_fs *ef, uint32_t handle, int isdir,
01149 struct emufs_vnode **ret)
01150 {
01151 struct vnode *v;
01152 struct emufs_vnode *ev;
01153 unsigned i, num;
01154 int result;
01155
01156 vfs_biglock_acquire();
01157 lock_acquire(ef->ef_emu->e_lock);
01158
01159 num = vnodearray_num(ef->ef_vnodes);
01160 for (i=0; i<num; i++) {
01161 v = vnodearray_get(ef->ef_vnodes, i);
01162 ev = v->vn_data;
01163 if (ev->ev_handle == handle) {
01164
01165
01166 VOP_INCREF(&ev->ev_v);
01167
01168 lock_release(ef->ef_emu->e_lock);
01169 vfs_biglock_release();
01170 *ret = ev;
01171 return 0;
01172 }
01173 }
01174
01175
01176
01177 ev = kmalloc(sizeof(struct emufs_vnode));
01178 if (ev==NULL) {
01179 lock_release(ef->ef_emu->e_lock);
01180 return ENOMEM;
01181 }
01182
01183 ev->ev_emu = ef->ef_emu;
01184 ev->ev_handle = handle;
01185
01186 result = VOP_INIT(&ev->ev_v, isdir ? &emufs_dirops : &emufs_fileops,
01187 &ef->ef_fs, ev);
01188 if (result) {
01189 lock_release(ef->ef_emu->e_lock);
01190 vfs_biglock_release();
01191 kfree(ev);
01192 return result;
01193 }
01194
01195 result = vnodearray_add(ef->ef_vnodes, &ev->ev_v, NULL);
01196 if (result) {
01197
01198 VOP_CLEANUP(&ev->ev_v);
01199 lock_release(ef->ef_emu->e_lock);
01200 vfs_biglock_release();
01201 kfree(ev);
01202 return result;
01203 }
01204
01205 lock_release(ef->ef_emu->e_lock);
01206 vfs_biglock_release();
01207
01208 *ret = ev;
01209 return 0;
01210 }
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223 static
01224 int
01225 emufs_sync(struct fs *fs)
01226 {
01227 (void)fs;
01228 return 0;
01229 }
01230
01231
01232
01233
01234 static
01235 const char *
01236 emufs_getvolname(struct fs *fs)
01237 {
01238
01239 (void)fs;
01240 return NULL;
01241 }
01242
01243
01244
01245
01246 static
01247 struct vnode *
01248 emufs_getroot(struct fs *fs)
01249 {
01250 struct emufs_fs *ef;
01251
01252 KASSERT(fs != NULL);
01253
01254 ef = fs->fs_data;
01255
01256 KASSERT(ef != NULL);
01257 KASSERT(ef->ef_root != NULL);
01258
01259 VOP_INCREF(&ef->ef_root->ev_v);
01260 return &ef->ef_root->ev_v;
01261 }
01262
01263
01264
01265
01266 static
01267 int
01268 emufs_unmount(struct fs *fs)
01269 {
01270
01271 (void)fs;
01272 return EBUSY;
01273 }
01274
01275
01276
01277
01278
01279
01280
01281
01282 static
01283 int
01284 emufs_addtovfs(struct emu_softc *sc, const char *devname)
01285 {
01286 struct emufs_fs *ef;
01287 int result;
01288
01289 ef = kmalloc(sizeof(struct emufs_fs));
01290 if (ef==NULL) {
01291 return ENOMEM;
01292 }
01293
01294 ef->ef_fs.fs_sync = emufs_sync;
01295 ef->ef_fs.fs_getvolname = emufs_getvolname;
01296 ef->ef_fs.fs_getroot = emufs_getroot;
01297 ef->ef_fs.fs_unmount = emufs_unmount;
01298 ef->ef_fs.fs_data = ef;
01299
01300 ef->ef_emu = sc;
01301 ef->ef_root = NULL;
01302 ef->ef_vnodes = vnodearray_create();
01303 if (ef->ef_vnodes == NULL) {
01304 kfree(ef);
01305 return ENOMEM;
01306 }
01307
01308 result = emufs_loadvnode(ef, EMU_ROOTHANDLE, 1, &ef->ef_root);
01309 if (result) {
01310 kfree(ef);
01311 return result;
01312 }
01313
01314 KASSERT(ef->ef_root!=NULL);
01315
01316 result = vfs_addfs(devname, &ef->ef_fs);
01317 if (result) {
01318 VOP_DECREF(&ef->ef_root->ev_v);
01319 kfree(ef);
01320 }
01321 return result;
01322 }
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 int
01333 config_emu(struct emu_softc *sc, int emuno)
01334 {
01335 char name[32];
01336
01337 sc->e_lock = lock_create("emufs-lock");
01338 if (sc->e_lock == NULL) {
01339 return ENOMEM;
01340 }
01341 sc->e_sem = sem_create("emufs-sem", 0);
01342 if (sc->e_sem == NULL) {
01343 lock_destroy(sc->e_lock);
01344 sc->e_lock = NULL;
01345 return ENOMEM;
01346 }
01347 sc->e_iobuf = bus_map_area(sc->e_busdata, sc->e_buspos, EMU_BUFFER);
01348
01349 snprintf(name, sizeof(name), "emu%d", emuno);
01350
01351 return emufs_addtovfs(sc, name);
01352 }