emu.c 24 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352
  1. /*
  2. * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
  3. * The President and Fellows of Harvard College.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the University nor the names of its contributors
  14. * may be used to endorse or promote products derived from this software
  15. * without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
  18. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  19. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  20. * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
  21. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  23. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  24. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  25. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  26. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  27. * SUCH DAMAGE.
  28. */
  29. /*
  30. * Emulator passthrough filesystem.
  31. *
  32. * The idea is that this appears as a filesystem in the VFS layer, and
  33. * passes VFS operations through a somewhat complicated "hardware"
  34. * interface to some simulated "hardware" in System/161 that accesses
  35. * the filesystem System/161 is running in.
  36. *
  37. * This makes it unnecessary to copy the system files to the simulated
  38. * disk, although we recommend doing so and trying running without this
  39. * device as part of testing your filesystem.
  40. */
  41. #include <types.h>
  42. #include <kern/errno.h>
  43. #include <kern/fcntl.h>
  44. #include <stat.h>
  45. #include <lib.h>
  46. #include <array.h>
  47. #include <uio.h>
  48. #include <synch.h>
  49. #include <lamebus/emu.h>
  50. #include <platform/bus.h>
  51. #include <vfs.h>
  52. #include <emufs.h>
  53. #include "autoconf.h"
  54. /* Register offsets */
  55. #define REG_HANDLE 0
  56. #define REG_OFFSET 4
  57. #define REG_IOLEN 8
  58. #define REG_OPER 12
  59. #define REG_RESULT 16
  60. /* I/O buffer offset */
  61. #define EMU_BUFFER 32768
  62. /* Operation codes for REG_OPER */
  63. #define EMU_OP_OPEN 1
  64. #define EMU_OP_CREATE 2
  65. #define EMU_OP_EXCLCREATE 3
  66. #define EMU_OP_CLOSE 4
  67. #define EMU_OP_READ 5
  68. #define EMU_OP_READDIR 6
  69. #define EMU_OP_WRITE 7
  70. #define EMU_OP_GETSIZE 8
  71. #define EMU_OP_TRUNC 9
  72. /* Result codes for REG_RESULT */
  73. #define EMU_RES_SUCCESS 1
  74. #define EMU_RES_BADHANDLE 2
  75. #define EMU_RES_BADOP 3
  76. #define EMU_RES_BADPATH 4
  77. #define EMU_RES_BADSIZE 5
  78. #define EMU_RES_EXISTS 6
  79. #define EMU_RES_ISDIR 7
  80. #define EMU_RES_MEDIA 8
  81. #define EMU_RES_NOHANDLES 9
  82. #define EMU_RES_NOSPACE 10
  83. #define EMU_RES_NOTDIR 11
  84. #define EMU_RES_UNKNOWN 12
  85. #define EMU_RES_UNSUPP 13
  86. ////////////////////////////////////////////////////////////
  87. //
  88. // Hardware ops
  89. //
  90. /*
  91. * Shortcut for reading a register
  92. */
  93. static
  94. inline
  95. uint32_t
  96. emu_rreg(struct emu_softc *sc, uint32_t reg)
  97. {
  98. return bus_read_register(sc->e_busdata, sc->e_buspos, reg);
  99. }
  100. /*
  101. * Shortcut for writing a register
  102. */
  103. static
  104. inline
  105. void
  106. emu_wreg(struct emu_softc *sc, uint32_t reg, uint32_t val)
  107. {
  108. bus_write_register(sc->e_busdata, sc->e_buspos, reg, val);
  109. }
  110. /*
  111. * Called by the underlying bus code when an interrupt happens
  112. */
  113. void
  114. emu_irq(void *dev)
  115. {
  116. struct emu_softc *sc = dev;
  117. sc->e_result = emu_rreg(sc, REG_RESULT);
  118. emu_wreg(sc, REG_RESULT, 0);
  119. V(sc->e_sem);
  120. }
  121. /*
  122. * Convert the error codes reported by the "hardware" to errnos.
  123. * Or, on cases that indicate a programming error in emu.c, panic.
  124. */
  125. static
  126. uint32_t
  127. translate_err(struct emu_softc *sc, uint32_t code)
  128. {
  129. switch (code) {
  130. case EMU_RES_SUCCESS: return 0;
  131. case EMU_RES_BADHANDLE:
  132. case EMU_RES_BADOP:
  133. case EMU_RES_BADSIZE:
  134. panic("emu%d: got fatal result code %d\n", sc->e_unit, code);
  135. case EMU_RES_BADPATH: return ENOENT;
  136. case EMU_RES_EXISTS: return EEXIST;
  137. case EMU_RES_ISDIR: return EISDIR;
  138. case EMU_RES_MEDIA: return EIO;
  139. case EMU_RES_NOHANDLES: return ENFILE;
  140. case EMU_RES_NOSPACE: return ENOSPC;
  141. case EMU_RES_NOTDIR: return ENOTDIR;
  142. case EMU_RES_UNKNOWN: return EIO;
  143. case EMU_RES_UNSUPP: return EUNIMP;
  144. }
  145. kprintf("emu%d: Unknown result code %d\n", sc->e_unit, code);
  146. return EAGAIN;
  147. }
  148. /*
  149. * Wait for an operation to complete, and return an errno for the result.
  150. */
  151. static
  152. int
  153. emu_waitdone(struct emu_softc *sc)
  154. {
  155. P(sc->e_sem);
  156. return translate_err(sc, sc->e_result);
  157. }
  158. /*
  159. * Common file open routine (for both VOP_LOOKUP and VOP_CREATE). Not
  160. * for VOP_OPEN. At the hardware level, we need to "open" files in
  161. * order to look at them, so by the time VOP_OPEN is called the
  162. * files are already open.
  163. */
  164. static
  165. int
  166. emu_open(struct emu_softc *sc, uint32_t handle, const char *name,
  167. bool create, bool excl, mode_t mode,
  168. uint32_t *newhandle, int *newisdir)
  169. {
  170. uint32_t op;
  171. int result;
  172. if (strlen(name)+1 > EMU_MAXIO) {
  173. return ENAMETOOLONG;
  174. }
  175. if (create && excl) {
  176. op = EMU_OP_EXCLCREATE;
  177. }
  178. else if (create) {
  179. op = EMU_OP_CREATE;
  180. }
  181. else {
  182. op = EMU_OP_OPEN;
  183. }
  184. /* mode isn't supported (yet?) */
  185. (void)mode;
  186. lock_acquire(sc->e_lock);
  187. strcpy(sc->e_iobuf, name);
  188. emu_wreg(sc, REG_IOLEN, strlen(name));
  189. emu_wreg(sc, REG_HANDLE, handle);
  190. emu_wreg(sc, REG_OPER, op);
  191. result = emu_waitdone(sc);
  192. if (result==0) {
  193. *newhandle = emu_rreg(sc, REG_HANDLE);
  194. *newisdir = emu_rreg(sc, REG_IOLEN)>0;
  195. }
  196. lock_release(sc->e_lock);
  197. return result;
  198. }
  199. /*
  200. * Routine for closing a file we opened at the hardware level.
  201. * This is not necessarily called at VOP_CLOSE time; it's called
  202. * at VOP_RECLAIM time.
  203. */
  204. static
  205. int
  206. emu_close(struct emu_softc *sc, uint32_t handle)
  207. {
  208. int result;
  209. bool mine;
  210. int retries = 0;
  211. mine = lock_do_i_hold(sc->e_lock);
  212. if (!mine) {
  213. lock_acquire(sc->e_lock);
  214. }
  215. while (1) {
  216. /* Retry operation up to 10 times */
  217. emu_wreg(sc, REG_HANDLE, handle);
  218. emu_wreg(sc, REG_OPER, EMU_OP_CLOSE);
  219. result = emu_waitdone(sc);
  220. if (result==EIO && retries < 10) {
  221. kprintf("emu%d: I/O error on close, retrying\n",
  222. sc->e_unit);
  223. retries++;
  224. continue;
  225. }
  226. break;
  227. }
  228. if (!mine) {
  229. lock_release(sc->e_lock);
  230. }
  231. return result;
  232. }
  233. /*
  234. * Common code for read and readdir.
  235. */
  236. static
  237. int
  238. emu_doread(struct emu_softc *sc, uint32_t handle, uint32_t len,
  239. uint32_t op, struct uio *uio)
  240. {
  241. int result;
  242. KASSERT(uio->uio_rw == UIO_READ);
  243. lock_acquire(sc->e_lock);
  244. emu_wreg(sc, REG_HANDLE, handle);
  245. emu_wreg(sc, REG_IOLEN, len);
  246. emu_wreg(sc, REG_OFFSET, uio->uio_offset);
  247. emu_wreg(sc, REG_OPER, op);
  248. result = emu_waitdone(sc);
  249. if (result) {
  250. goto out;
  251. }
  252. result = uiomove(sc->e_iobuf, emu_rreg(sc, REG_IOLEN), uio);
  253. uio->uio_offset = emu_rreg(sc, REG_OFFSET);
  254. out:
  255. lock_release(sc->e_lock);
  256. return result;
  257. }
  258. /*
  259. * Read from a hardware-level file handle.
  260. */
  261. static
  262. int
  263. emu_read(struct emu_softc *sc, uint32_t handle, uint32_t len,
  264. struct uio *uio)
  265. {
  266. return emu_doread(sc, handle, len, EMU_OP_READ, uio);
  267. }
  268. /*
  269. * Read a directory entry from a hardware-level file handle.
  270. */
  271. static
  272. int
  273. emu_readdir(struct emu_softc *sc, uint32_t handle, uint32_t len,
  274. struct uio *uio)
  275. {
  276. return emu_doread(sc, handle, len, EMU_OP_READDIR, uio);
  277. }
  278. /*
  279. * Write to a hardware-level file handle.
  280. */
  281. static
  282. int
  283. emu_write(struct emu_softc *sc, uint32_t handle, uint32_t len,
  284. struct uio *uio)
  285. {
  286. int result;
  287. KASSERT(uio->uio_rw == UIO_WRITE);
  288. lock_acquire(sc->e_lock);
  289. emu_wreg(sc, REG_HANDLE, handle);
  290. emu_wreg(sc, REG_IOLEN, len);
  291. emu_wreg(sc, REG_OFFSET, uio->uio_offset);
  292. result = uiomove(sc->e_iobuf, len, uio);
  293. if (result) {
  294. goto out;
  295. }
  296. emu_wreg(sc, REG_OPER, EMU_OP_WRITE);
  297. result = emu_waitdone(sc);
  298. out:
  299. lock_release(sc->e_lock);
  300. return result;
  301. }
  302. /*
  303. * Get the file size associated with a hardware-level file handle.
  304. */
  305. static
  306. int
  307. emu_getsize(struct emu_softc *sc, uint32_t handle, off_t *retval)
  308. {
  309. int result;
  310. lock_acquire(sc->e_lock);
  311. emu_wreg(sc, REG_HANDLE, handle);
  312. emu_wreg(sc, REG_OPER, EMU_OP_GETSIZE);
  313. result = emu_waitdone(sc);
  314. if (result==0) {
  315. *retval = emu_rreg(sc, REG_IOLEN);
  316. }
  317. lock_release(sc->e_lock);
  318. return result;
  319. }
  320. /*
  321. * Truncate a hardware-level file handle.
  322. */
  323. static
  324. int
  325. emu_trunc(struct emu_softc *sc, uint32_t handle, off_t len)
  326. {
  327. int result;
  328. lock_acquire(sc->e_lock);
  329. emu_wreg(sc, REG_HANDLE, handle);
  330. emu_wreg(sc, REG_IOLEN, len);
  331. emu_wreg(sc, REG_OPER, EMU_OP_TRUNC);
  332. result = emu_waitdone(sc);
  333. lock_release(sc->e_lock);
  334. return result;
  335. }
  336. //
  337. ////////////////////////////////////////////////////////////
  338. ////////////////////////////////////////////////////////////
  339. //
  340. // vnode functions
  341. //
  342. // at bottom of this section
  343. static int emufs_loadvnode(struct emufs_fs *ef, uint32_t handle, int isdir,
  344. struct emufs_vnode **ret);
  345. /*
  346. * VOP_OPEN on files
  347. */
  348. static
  349. int
  350. emufs_open(struct vnode *v, int openflags)
  351. {
  352. /*
  353. * At this level we do not need to handle O_CREAT, O_EXCL, or O_TRUNC.
  354. * We *would* need to handle O_APPEND, but we don't support it.
  355. *
  356. * Any of O_RDONLY, O_WRONLY, and O_RDWR are valid, so we don't need
  357. * to check that either.
  358. */
  359. if (openflags & O_APPEND) {
  360. return EUNIMP;
  361. }
  362. (void)v;
  363. return 0;
  364. }
  365. /*
  366. * VOP_OPEN on directories
  367. */
  368. static
  369. int
  370. emufs_opendir(struct vnode *v, int openflags)
  371. {
  372. switch (openflags & O_ACCMODE) {
  373. case O_RDONLY:
  374. break;
  375. case O_WRONLY:
  376. case O_RDWR:
  377. default:
  378. return EISDIR;
  379. }
  380. if (openflags & O_APPEND) {
  381. return EISDIR;
  382. }
  383. (void)v;
  384. return 0;
  385. }
  386. /*
  387. * VOP_CLOSE
  388. */
  389. static
  390. int
  391. emufs_close(struct vnode *v)
  392. {
  393. (void)v;
  394. return 0;
  395. }
  396. /*
  397. * VOP_RECLAIM
  398. *
  399. * Reclaim should make an effort to returning errors other than EBUSY.
  400. */
  401. static
  402. int
  403. emufs_reclaim(struct vnode *v)
  404. {
  405. struct emufs_vnode *ev = v->vn_data;
  406. struct emufs_fs *ef = v->vn_fs->fs_data;
  407. unsigned ix, i, num;
  408. int result;
  409. /*
  410. * Need both of these locks, e_lock to protect the device
  411. * and vfs_biglock to protect the fs-related material.
  412. */
  413. vfs_biglock_acquire();
  414. lock_acquire(ef->ef_emu->e_lock);
  415. if (ev->ev_v.vn_refcount != 1) {
  416. lock_release(ef->ef_emu->e_lock);
  417. vfs_biglock_release();
  418. return EBUSY;
  419. }
  420. /* emu_close retries on I/O error */
  421. result = emu_close(ev->ev_emu, ev->ev_handle);
  422. if (result) {
  423. lock_release(ef->ef_emu->e_lock);
  424. vfs_biglock_release();
  425. return result;
  426. }
  427. num = vnodearray_num(ef->ef_vnodes);
  428. ix = num;
  429. for (i=0; i<num; i++) {
  430. struct vnode *vx;
  431. vx = vnodearray_get(ef->ef_vnodes, i);
  432. if (vx == v) {
  433. ix = i;
  434. break;
  435. }
  436. }
  437. if (ix == num) {
  438. panic("emu%d: reclaim vnode %u not in vnode pool\n",
  439. ef->ef_emu->e_unit, ev->ev_handle);
  440. }
  441. vnodearray_remove(ef->ef_vnodes, ix);
  442. VOP_CLEANUP(&ev->ev_v);
  443. lock_release(ef->ef_emu->e_lock);
  444. vfs_biglock_release();
  445. kfree(ev);
  446. return 0;
  447. }
  448. /*
  449. * VOP_READ
  450. */
  451. static
  452. int
  453. emufs_read(struct vnode *v, struct uio *uio)
  454. {
  455. struct emufs_vnode *ev = v->vn_data;
  456. uint32_t amt;
  457. size_t oldresid;
  458. int result;
  459. KASSERT(uio->uio_rw==UIO_READ);
  460. while (uio->uio_resid > 0) {
  461. amt = uio->uio_resid;
  462. if (amt > EMU_MAXIO) {
  463. amt = EMU_MAXIO;
  464. }
  465. oldresid = uio->uio_resid;
  466. result = emu_read(ev->ev_emu, ev->ev_handle, amt, uio);
  467. if (result) {
  468. return result;
  469. }
  470. if (uio->uio_resid == oldresid) {
  471. /* nothing read - EOF */
  472. break;
  473. }
  474. }
  475. return 0;
  476. }
  477. /*
  478. * VOP_READDIR
  479. */
  480. static
  481. int
  482. emufs_getdirentry(struct vnode *v, struct uio *uio)
  483. {
  484. struct emufs_vnode *ev = v->vn_data;
  485. uint32_t amt;
  486. KASSERT(uio->uio_rw==UIO_READ);
  487. amt = uio->uio_resid;
  488. if (amt > EMU_MAXIO) {
  489. amt = EMU_MAXIO;
  490. }
  491. return emu_readdir(ev->ev_emu, ev->ev_handle, amt, uio);
  492. }
  493. /*
  494. * VOP_WRITE
  495. */
  496. static
  497. int
  498. emufs_write(struct vnode *v, struct uio *uio)
  499. {
  500. struct emufs_vnode *ev = v->vn_data;
  501. uint32_t amt;
  502. size_t oldresid;
  503. int result;
  504. KASSERT(uio->uio_rw==UIO_WRITE);
  505. while (uio->uio_resid > 0) {
  506. amt = uio->uio_resid;
  507. if (amt > EMU_MAXIO) {
  508. amt = EMU_MAXIO;
  509. }
  510. oldresid = uio->uio_resid;
  511. result = emu_write(ev->ev_emu, ev->ev_handle, amt, uio);
  512. if (result) {
  513. return result;
  514. }
  515. if (uio->uio_resid == oldresid) {
  516. /* nothing written...? */
  517. break;
  518. }
  519. }
  520. return 0;
  521. }
  522. /*
  523. * VOP_IOCTL
  524. */
  525. static
  526. int
  527. emufs_ioctl(struct vnode *v, int op, userptr_t data)
  528. {
  529. /*
  530. * No ioctls.
  531. */
  532. (void)v;
  533. (void)op;
  534. (void)data;
  535. return EINVAL;
  536. }
  537. /*
  538. * VOP_STAT
  539. */
  540. static
  541. int
  542. emufs_stat(struct vnode *v, struct stat *statbuf)
  543. {
  544. struct emufs_vnode *ev = v->vn_data;
  545. int result;
  546. bzero(statbuf, sizeof(struct stat));
  547. result = emu_getsize(ev->ev_emu, ev->ev_handle, &statbuf->st_size);
  548. if (result) {
  549. return result;
  550. }
  551. result = VOP_GETTYPE(v, &statbuf->st_mode);
  552. if (result) {
  553. return result;
  554. }
  555. statbuf->st_mode |= 0644; /* possibly a lie */
  556. statbuf->st_nlink = 1; /* might be a lie, but doesn't matter much */
  557. statbuf->st_blocks = 0; /* almost certainly a lie */
  558. return 0;
  559. }
  560. /*
  561. * VOP_GETTYPE for files
  562. */
  563. static
  564. int
  565. emufs_file_gettype(struct vnode *v, uint32_t *result)
  566. {
  567. (void)v;
  568. *result = S_IFREG;
  569. return 0;
  570. }
  571. /*
  572. * VOP_GETTYPE for directories
  573. */
  574. static
  575. int
  576. emufs_dir_gettype(struct vnode *v, uint32_t *result)
  577. {
  578. (void)v;
  579. *result = S_IFDIR;
  580. return 0;
  581. }
  582. /*
  583. * VOP_TRYSEEK
  584. */
  585. static
  586. int
  587. emufs_tryseek(struct vnode *v, off_t pos)
  588. {
  589. if (pos<0) {
  590. return EINVAL;
  591. }
  592. /* Allow anything else */
  593. (void)v;
  594. return 0;
  595. }
  596. /*
  597. * VOP_FSYNC
  598. */
  599. static
  600. int
  601. emufs_fsync(struct vnode *v)
  602. {
  603. (void)v;
  604. return 0;
  605. }
  606. /*
  607. * VOP_TRUNCATE
  608. */
  609. static
  610. int
  611. emufs_truncate(struct vnode *v, off_t len)
  612. {
  613. struct emufs_vnode *ev = v->vn_data;
  614. return emu_trunc(ev->ev_emu, ev->ev_handle, len);
  615. }
  616. /*
  617. * VOP_CREAT
  618. */
  619. static
  620. int
  621. emufs_creat(struct vnode *dir, const char *name, bool excl, mode_t mode,
  622. struct vnode **ret)
  623. {
  624. struct emufs_vnode *ev = dir->vn_data;
  625. struct emufs_fs *ef = dir->vn_fs->fs_data;
  626. struct emufs_vnode *newguy;
  627. uint32_t handle;
  628. int result;
  629. int isdir;
  630. result = emu_open(ev->ev_emu, ev->ev_handle, name, true, excl, mode,
  631. &handle, &isdir);
  632. if (result) {
  633. return result;
  634. }
  635. result = emufs_loadvnode(ef, handle, isdir, &newguy);
  636. if (result) {
  637. emu_close(ev->ev_emu, handle);
  638. return result;
  639. }
  640. *ret = &newguy->ev_v;
  641. return 0;
  642. }
  643. /*
  644. * VOP_LOOKUP
  645. */
  646. static
  647. int
  648. emufs_lookup(struct vnode *dir, char *pathname, struct vnode **ret)
  649. {
  650. struct emufs_vnode *ev = dir->vn_data;
  651. struct emufs_fs *ef = dir->vn_fs->fs_data;
  652. struct emufs_vnode *newguy;
  653. uint32_t handle;
  654. int result;
  655. int isdir;
  656. result = emu_open(ev->ev_emu, ev->ev_handle, pathname, false, false, 0,
  657. &handle, &isdir);
  658. if (result) {
  659. return result;
  660. }
  661. result = emufs_loadvnode(ef, handle, isdir, &newguy);
  662. if (result) {
  663. emu_close(ev->ev_emu, handle);
  664. return result;
  665. }
  666. *ret = &newguy->ev_v;
  667. return 0;
  668. }
  669. /*
  670. * VOP_LOOKPARENT
  671. */
  672. static
  673. int
  674. emufs_lookparent(struct vnode *dir, char *pathname, struct vnode **ret,
  675. char *buf, size_t len)
  676. {
  677. char *s;
  678. s = strrchr(pathname, '/');
  679. if (s==NULL) {
  680. /* just a last component, no directory part */
  681. if (strlen(pathname)+1 > len) {
  682. return ENAMETOOLONG;
  683. }
  684. VOP_INCREF(dir);
  685. *ret = dir;
  686. strcpy(buf, pathname);
  687. return 0;
  688. }
  689. *s = 0;
  690. s++;
  691. if (strlen(s)+1 > len) {
  692. return ENAMETOOLONG;
  693. }
  694. strcpy(buf, s);
  695. return emufs_lookup(dir, pathname, ret);
  696. }
  697. /*
  698. * VOP_NAMEFILE
  699. */
  700. static
  701. int
  702. emufs_namefile(struct vnode *v, struct uio *uio)
  703. {
  704. struct emufs_vnode *ev = v->vn_data;
  705. struct emufs_fs *ef = v->vn_fs->fs_data;
  706. if (ev == ef->ef_root) {
  707. /*
  708. * Root directory - name is empty string
  709. */
  710. return 0;
  711. }
  712. (void)uio;
  713. return EUNIMP;
  714. }
  715. /*
  716. * VOP_MMAP
  717. */
  718. static
  719. int
  720. emufs_mmap(struct vnode *v)
  721. {
  722. (void)v;
  723. return EUNIMP;
  724. }
  725. //////////////////////////////
  726. /*
  727. * Bits not implemented at all on emufs
  728. */
  729. static
  730. int
  731. emufs_dir_tryseek(struct vnode *v, off_t pos)
  732. {
  733. (void)v;
  734. (void)pos;
  735. return EUNIMP;
  736. }
  737. static
  738. int
  739. emufs_symlink(struct vnode *v, const char *contents, const char *name)
  740. {
  741. (void)v;
  742. (void)contents;
  743. (void)name;
  744. return EUNIMP;
  745. }
  746. static
  747. int
  748. emufs_mkdir(struct vnode *v, const char *name, mode_t mode)
  749. {
  750. (void)v;
  751. (void)name;
  752. (void)mode;
  753. return EUNIMP;
  754. }
  755. static
  756. int
  757. emufs_link(struct vnode *v, const char *name, struct vnode *target)
  758. {
  759. (void)v;
  760. (void)name;
  761. (void)target;
  762. return EUNIMP;
  763. }
  764. static
  765. int
  766. emufs_remove(struct vnode *v, const char *name)
  767. {
  768. (void)v;
  769. (void)name;
  770. return EUNIMP;
  771. }
  772. static
  773. int
  774. emufs_rmdir(struct vnode *v, const char *name)
  775. {
  776. (void)v;
  777. (void)name;
  778. return EUNIMP;
  779. }
  780. static
  781. int
  782. emufs_rename(struct vnode *v1, const char *n1,
  783. struct vnode *v2, const char *n2)
  784. {
  785. (void)v1;
  786. (void)n1;
  787. (void)v2;
  788. (void)n2;
  789. return EUNIMP;
  790. }
  791. //////////////////////////////
  792. /*
  793. * Routines that fail
  794. *
  795. * It is kind of silly to write these out each with their particular
  796. * arguments; however, portable C doesn't let you cast function
  797. * pointers with different argument signatures even if the arguments
  798. * are never used.
  799. *
  800. * The BSD approach (all vnode ops take a vnode pointer and a void
  801. * pointer that's cast to a op-specific args structure) avoids this
  802. * problem but is otherwise not very appealing.
  803. */
  804. static
  805. int
  806. emufs_void_op_isdir(struct vnode *v)
  807. {
  808. (void)v;
  809. return EISDIR;
  810. }
  811. static
  812. int
  813. emufs_uio_op_isdir(struct vnode *v, struct uio *uio)
  814. {
  815. (void)v;
  816. (void)uio;
  817. return EISDIR;
  818. }
  819. static
  820. int
  821. emufs_uio_op_notdir(struct vnode *v, struct uio *uio)
  822. {
  823. (void)v;
  824. (void)uio;
  825. return ENOTDIR;
  826. }
  827. static
  828. int
  829. emufs_name_op_notdir(struct vnode *v, const char *name)
  830. {
  831. (void)v;
  832. (void)name;
  833. return ENOTDIR;
  834. }
  835. static
  836. int
  837. emufs_readlink_notlink(struct vnode *v, struct uio *uio)
  838. {
  839. (void)v;
  840. (void)uio;
  841. return EINVAL;
  842. }
  843. static
  844. int
  845. emufs_creat_notdir(struct vnode *v, const char *name, bool excl, mode_t mode,
  846. struct vnode **retval)
  847. {
  848. (void)v;
  849. (void)name;
  850. (void)excl;
  851. (void)mode;
  852. (void)retval;
  853. return ENOTDIR;
  854. }
  855. static
  856. int
  857. emufs_symlink_notdir(struct vnode *v, const char *contents, const char *name)
  858. {
  859. (void)v;
  860. (void)contents;
  861. (void)name;
  862. return ENOTDIR;
  863. }
  864. static
  865. int
  866. emufs_mkdir_notdir(struct vnode *v, const char *name, mode_t mode)
  867. {
  868. (void)v;
  869. (void)name;
  870. (void)mode;
  871. return ENOTDIR;
  872. }
  873. static
  874. int
  875. emufs_link_notdir(struct vnode *v, const char *name, struct vnode *target)
  876. {
  877. (void)v;
  878. (void)name;
  879. (void)target;
  880. return ENOTDIR;
  881. }
  882. static
  883. int
  884. emufs_rename_notdir(struct vnode *v1, const char *n1,
  885. struct vnode *v2, const char *n2)
  886. {
  887. (void)v1;
  888. (void)n1;
  889. (void)v2;
  890. (void)n2;
  891. return ENOTDIR;
  892. }
  893. static
  894. int
  895. emufs_lookup_notdir(struct vnode *v, char *pathname, struct vnode **result)
  896. {
  897. (void)v;
  898. (void)pathname;
  899. (void)result;
  900. return ENOTDIR;
  901. }
  902. static
  903. int
  904. emufs_lookparent_notdir(struct vnode *v, char *pathname, struct vnode **result,
  905. char *buf, size_t len)
  906. {
  907. (void)v;
  908. (void)pathname;
  909. (void)result;
  910. (void)buf;
  911. (void)len;
  912. return ENOTDIR;
  913. }
  914. static
  915. int
  916. emufs_truncate_isdir(struct vnode *v, off_t len)
  917. {
  918. (void)v;
  919. (void)len;
  920. return ENOTDIR;
  921. }
  922. //////////////////////////////
  923. /*
  924. * Function table for emufs files.
  925. */
  926. static const struct vnode_ops emufs_fileops = {
  927. VOP_MAGIC, /* mark this a valid vnode ops table */
  928. emufs_open,
  929. emufs_close,
  930. emufs_reclaim,
  931. emufs_read,
  932. emufs_readlink_notlink,
  933. emufs_uio_op_notdir, /* getdirentry */
  934. emufs_write,
  935. emufs_ioctl,
  936. emufs_stat,
  937. emufs_file_gettype,
  938. emufs_tryseek,
  939. emufs_fsync,
  940. emufs_mmap,
  941. emufs_truncate,
  942. emufs_uio_op_notdir, /* namefile */
  943. emufs_creat_notdir,
  944. emufs_symlink_notdir,
  945. emufs_mkdir_notdir,
  946. emufs_link_notdir,
  947. emufs_name_op_notdir, /* remove */
  948. emufs_name_op_notdir, /* rmdir */
  949. emufs_rename_notdir,
  950. emufs_lookup_notdir,
  951. emufs_lookparent_notdir,
  952. };
  953. /*
  954. * Function table for emufs directories.
  955. */
  956. static const struct vnode_ops emufs_dirops = {
  957. VOP_MAGIC, /* mark this a valid vnode ops table */
  958. emufs_opendir,
  959. emufs_close,
  960. emufs_reclaim,
  961. emufs_uio_op_isdir, /* read */
  962. emufs_uio_op_isdir, /* readlink */
  963. emufs_getdirentry,
  964. emufs_uio_op_isdir, /* write */
  965. emufs_ioctl,
  966. emufs_stat,
  967. emufs_dir_gettype,
  968. emufs_dir_tryseek,
  969. emufs_void_op_isdir, /* fsync */
  970. emufs_void_op_isdir, /* mmap */
  971. emufs_truncate_isdir,
  972. emufs_namefile,
  973. emufs_creat,
  974. emufs_symlink,
  975. emufs_mkdir,
  976. emufs_link,
  977. emufs_remove,
  978. emufs_rmdir,
  979. emufs_rename,
  980. emufs_lookup,
  981. emufs_lookparent,
  982. };
  983. /*
  984. * Function to load a vnode into memory.
  985. */
  986. static
  987. int
  988. emufs_loadvnode(struct emufs_fs *ef, uint32_t handle, int isdir,
  989. struct emufs_vnode **ret)
  990. {
  991. struct vnode *v;
  992. struct emufs_vnode *ev;
  993. unsigned i, num;
  994. int result;
  995. vfs_biglock_acquire();
  996. lock_acquire(ef->ef_emu->e_lock);
  997. num = vnodearray_num(ef->ef_vnodes);
  998. for (i=0; i<num; i++) {
  999. v = vnodearray_get(ef->ef_vnodes, i);
  1000. ev = v->vn_data;
  1001. if (ev->ev_handle == handle) {
  1002. /* Found */
  1003. VOP_INCREF(&ev->ev_v);
  1004. lock_release(ef->ef_emu->e_lock);
  1005. vfs_biglock_release();
  1006. *ret = ev;
  1007. return 0;
  1008. }
  1009. }
  1010. /* Didn't have one; create it */
  1011. ev = kmalloc(sizeof(struct emufs_vnode));
  1012. if (ev==NULL) {
  1013. lock_release(ef->ef_emu->e_lock);
  1014. return ENOMEM;
  1015. }
  1016. ev->ev_emu = ef->ef_emu;
  1017. ev->ev_handle = handle;
  1018. result = VOP_INIT(&ev->ev_v, isdir ? &emufs_dirops : &emufs_fileops,
  1019. &ef->ef_fs, ev);
  1020. if (result) {
  1021. lock_release(ef->ef_emu->e_lock);
  1022. vfs_biglock_release();
  1023. kfree(ev);
  1024. return result;
  1025. }
  1026. result = vnodearray_add(ef->ef_vnodes, &ev->ev_v, NULL);
  1027. if (result) {
  1028. /* note: VOP_CLEANUP undoes VOP_INIT - it does not kfree */
  1029. VOP_CLEANUP(&ev->ev_v);
  1030. lock_release(ef->ef_emu->e_lock);
  1031. vfs_biglock_release();
  1032. kfree(ev);
  1033. return result;
  1034. }
  1035. lock_release(ef->ef_emu->e_lock);
  1036. vfs_biglock_release();
  1037. *ret = ev;
  1038. return 0;
  1039. }
  1040. //
  1041. ////////////////////////////////////////////////////////////
  1042. ////////////////////////////////////////////////////////////
  1043. //
  1044. // Whole-filesystem functions
  1045. //
  1046. /*
  1047. * FSOP_SYNC
  1048. */
  1049. static
  1050. int
  1051. emufs_sync(struct fs *fs)
  1052. {
  1053. (void)fs;
  1054. return 0;
  1055. }
  1056. /*
  1057. * FSOP_GETVOLNAME
  1058. */
  1059. static
  1060. const char *
  1061. emufs_getvolname(struct fs *fs)
  1062. {
  1063. /* We don't have a volume name beyond the device name */
  1064. (void)fs;
  1065. return NULL;
  1066. }
  1067. /*
  1068. * FSOP_GETROOT
  1069. */
  1070. static
  1071. struct vnode *
  1072. emufs_getroot(struct fs *fs)
  1073. {
  1074. struct emufs_fs *ef;
  1075. KASSERT(fs != NULL);
  1076. ef = fs->fs_data;
  1077. KASSERT(ef != NULL);
  1078. KASSERT(ef->ef_root != NULL);
  1079. VOP_INCREF(&ef->ef_root->ev_v);
  1080. return &ef->ef_root->ev_v;
  1081. }
  1082. /*
  1083. * FSOP_UNMOUNT
  1084. */
  1085. static
  1086. int
  1087. emufs_unmount(struct fs *fs)
  1088. {
  1089. /* Always prohibit unmount, as we're not really "mounted" */
  1090. (void)fs;
  1091. return EBUSY;
  1092. }
  1093. /*
  1094. * Routine for "mounting" an emufs - we're not really mounted in the
  1095. * sense that the VFS understands that term, because we're not
  1096. * connected to a block device.
  1097. *
  1098. * Basically, we just add ourselves to the name list in the VFS layer.
  1099. */
  1100. static
  1101. int
  1102. emufs_addtovfs(struct emu_softc *sc, const char *devname)
  1103. {
  1104. struct emufs_fs *ef;
  1105. int result;
  1106. ef = kmalloc(sizeof(struct emufs_fs));
  1107. if (ef==NULL) {
  1108. return ENOMEM;
  1109. }
  1110. ef->ef_fs.fs_sync = emufs_sync;
  1111. ef->ef_fs.fs_getvolname = emufs_getvolname;
  1112. ef->ef_fs.fs_getroot = emufs_getroot;
  1113. ef->ef_fs.fs_unmount = emufs_unmount;
  1114. ef->ef_fs.fs_data = ef;
  1115. ef->ef_emu = sc;
  1116. ef->ef_root = NULL;
  1117. ef->ef_vnodes = vnodearray_create();
  1118. if (ef->ef_vnodes == NULL) {
  1119. kfree(ef);
  1120. return ENOMEM;
  1121. }
  1122. result = emufs_loadvnode(ef, EMU_ROOTHANDLE, 1, &ef->ef_root);
  1123. if (result) {
  1124. kfree(ef);
  1125. return result;
  1126. }
  1127. KASSERT(ef->ef_root!=NULL);
  1128. result = vfs_addfs(devname, &ef->ef_fs);
  1129. if (result) {
  1130. VOP_DECREF(&ef->ef_root->ev_v);
  1131. kfree(ef);
  1132. }
  1133. return result;
  1134. }
  1135. //
  1136. ////////////////////////////////////////////////////////////
  1137. /*
  1138. * Config routine called by autoconf stuff.
  1139. *
  1140. * Initialize our data, then add ourselves to the VFS layer.
  1141. */
  1142. int
  1143. config_emu(struct emu_softc *sc, int emuno)
  1144. {
  1145. char name[32];
  1146. sc->e_lock = lock_create("emufs-lock");
  1147. if (sc->e_lock == NULL) {
  1148. return ENOMEM;
  1149. }
  1150. sc->e_sem = sem_create("emufs-sem", 0);
  1151. if (sc->e_sem == NULL) {
  1152. lock_destroy(sc->e_lock);
  1153. sc->e_lock = NULL;
  1154. return ENOMEM;
  1155. }
  1156. sc->e_iobuf = bus_map_area(sc->e_busdata, sc->e_buspos, EMU_BUFFER);
  1157. snprintf(name, sizeof(name), "emu%d", emuno);
  1158. return emufs_addtovfs(sc, name);
  1159. }