《操作系统》的实验代码。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

167 lines
4.5 KiB

12 years ago
  1. #include <defs.h>
  2. #include <string.h>
  3. #include <stat.h>
  4. #include <dev.h>
  5. #include <inode.h>
  6. #include <unistd.h>
  7. #include <error.h>
  8. /*
  9. * dev_open - Called for each open().
  10. */
  11. static int
  12. dev_open(struct inode *node, uint32_t open_flags) {
  13. if (open_flags & (O_CREAT | O_TRUNC | O_EXCL | O_APPEND)) {
  14. return -E_INVAL;
  15. }
  16. struct device *dev = vop_info(node, device);
  17. return dop_open(dev, open_flags);
  18. }
  19. /*
  20. * dev_close - Called on the last close(). Just pass through.
  21. */
  22. static int
  23. dev_close(struct inode *node) {
  24. struct device *dev = vop_info(node, device);
  25. return dop_close(dev);
  26. }
  27. /*
  28. * dev_read -Called for read. Hand off to iobuf.
  29. */
  30. static int
  31. dev_read(struct inode *node, struct iobuf *iob) {
  32. struct device *dev = vop_info(node, device);
  33. return dop_io(dev, iob, 0);
  34. }
  35. /*
  36. * dev_write -Called for write. Hand off to iobuf.
  37. */
  38. static int
  39. dev_write(struct inode *node, struct iobuf *iob) {
  40. struct device *dev = vop_info(node, device);
  41. return dop_io(dev, iob, 1);
  42. }
  43. /*
  44. * dev_ioctl - Called for ioctl(). Just pass through.
  45. */
  46. static int
  47. dev_ioctl(struct inode *node, int op, void *data) {
  48. struct device *dev = vop_info(node, device);
  49. return dop_ioctl(dev, op, data);
  50. }
  51. /*
  52. * dev_fstat - Called for stat().
  53. * Set the type and the size (block devices only).
  54. * The link count for a device is always 1.
  55. */
  56. static int
  57. dev_fstat(struct inode *node, struct stat *stat) {
  58. int ret;
  59. memset(stat, 0, sizeof(struct stat));
  60. if ((ret = vop_gettype(node, &(stat->st_mode))) != 0) {
  61. return ret;
  62. }
  63. struct device *dev = vop_info(node, device);
  64. stat->st_nlinks = 1;
  65. stat->st_blocks = dev->d_blocks;
  66. stat->st_size = stat->st_blocks * dev->d_blocksize;
  67. return 0;
  68. }
  69. /*
  70. * dev_gettype - Return the type. A device is a "block device" if it has a known
  71. * length. A device that generates data in a stream is a "character
  72. * device".
  73. */
  74. static int
  75. dev_gettype(struct inode *node, uint32_t *type_store) {
  76. struct device *dev = vop_info(node, device);
  77. *type_store = (dev->d_blocks > 0) ? S_IFBLK : S_IFCHR;
  78. return 0;
  79. }
  80. /*
  81. * dev_tryseek - Attempt a seek.
  82. * For block devices, require block alignment.
  83. * For character devices, prohibit seeking entirely.
  84. */
  85. static int
  86. dev_tryseek(struct inode *node, off_t pos) {
  87. struct device *dev = vop_info(node, device);
  88. if (dev->d_blocks > 0) {
  89. if ((pos % dev->d_blocksize) == 0) {
  90. if (pos >= 0 && pos < dev->d_blocks * dev->d_blocksize) {
  91. return 0;
  92. }
  93. }
  94. }
  95. return -E_INVAL;
  96. }
  97. /*
  98. * dev_lookup - Name lookup.
  99. *
  100. * One interesting feature of device:name pathname syntax is that you
  101. * can implement pathnames on arbitrary devices. For instance, if you
  102. * had a graphics device that supported multiple resolutions (which we
  103. * don't), you might arrange things so that you could open it with
  104. * pathnames like "video:800x600/24bpp" in order to select the operating
  105. * mode.
  106. *
  107. * However, we have no support for this in the base system.
  108. */
  109. static int
  110. dev_lookup(struct inode *node, char *path, struct inode **node_store) {
  111. if (*path != '\0') {
  112. return -E_NOENT;
  113. }
  114. vop_ref_inc(node);
  115. *node_store = node;
  116. return 0;
  117. }
  118. /*
  119. * Function table for device inodes.
  120. */
  121. static const struct inode_ops dev_node_ops = {
  122. .vop_magic = VOP_MAGIC,
  123. .vop_open = dev_open,
  124. .vop_close = dev_close,
  125. .vop_read = dev_read,
  126. .vop_write = dev_write,
  127. .vop_fstat = dev_fstat,
  128. .vop_ioctl = dev_ioctl,
  129. .vop_gettype = dev_gettype,
  130. .vop_tryseek = dev_tryseek,
  131. .vop_lookup = dev_lookup,
  132. };
  133. #define init_device(x) \
  134. do { \
  135. extern void dev_init_##x(void); \
  136. dev_init_##x(); \
  137. } while (0)
  138. /* dev_init - Initialization functions for builtin vfs-level devices. */
  139. void
  140. dev_init(void) {
  141. // init_device(null);
  142. init_device(stdin);
  143. init_device(stdout);
  144. init_device(disk0);
  145. }
  146. /* dev_create_inode - Create inode for a vfs-level device. */
  147. struct inode *
  148. dev_create_inode(void) {
  149. struct inode *node;
  150. if ((node = alloc_inode(device)) != NULL) {
  151. vop_init(node, &dev_node_ops, NULL);
  152. }
  153. return node;
  154. }