PageRenderTime 46ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/andromeda/drivers.c

https://code.google.com/
C | 267 lines | 206 code | 36 blank | 25 comment | 37 complexity | 7541d44b763cbeedb36c07dc63794db1 MD5 | raw file
Possible License(s): GPL-3.0
  1. /*
  2. * Andromeda, The educational operatingsystem
  3. * Copyright (C) 2011 Bart Kuivenhoven
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <stdlib.h>
  19. #include <andromeda/drivers.h>
  20. #include <andromeda/system.h>
  21. #include <drivers/root.h>
  22. #include <fs/vfs.h>
  23. static int drv_setup_io(struct device *dev, struct driver *drv,
  24. struct vfile *io, vfs_read_hook_t, vfs_write_hook_t);
  25. struct device dev_root;
  26. uint64_t dev_id = 0;
  27. mutex_t dev_id_lock;
  28. uint64_t virt_bus = 0;
  29. uint64_t lgcy_bus = 0;
  30. /** Return the number of detected CPU's */
  31. int dev_detect_cpus(struct device* root)
  32. {
  33. return -E_NOFUNCTION;
  34. }
  35. int dev_root_init()
  36. {
  37. struct device* root = &dev_root;
  38. memset(root, 0, sizeof(struct device));
  39. root->driver = kmalloc(sizeof(struct driver));
  40. memset(root->driver, 0, sizeof(struct driver));
  41. drv_root_init(root); /** Call to driver, not device!!! */
  42. // if (dev_detect_cpus(root) <= 0)
  43. // {
  44. // panic("Couldn't find any CPU's!");
  45. // }
  46. return -E_SUCCESS;
  47. }
  48. int device_recurse_suspend(struct device* this)
  49. {
  50. struct device* carriage = this->children;
  51. while(carriage != NULL)
  52. {
  53. carriage->driver->suspend(carriage);
  54. carriage = carriage->next;
  55. }
  56. return -E_SUCCESS;
  57. }
  58. int device_recurse_resume(struct device* this)
  59. {
  60. struct device* carriage = this->children;
  61. while(carriage != NULL)
  62. {
  63. carriage->driver->resume(carriage);
  64. carriage = carriage->next;
  65. }
  66. return -E_SUCCESS;
  67. }
  68. int device_attach(struct device* this, struct device* child)
  69. {
  70. if (this->children == NULL)
  71. {
  72. this->children = child;
  73. return -E_SUCCESS;
  74. }
  75. struct device* carriage = this->children;
  76. struct device* last = carriage;
  77. while (carriage != NULL)
  78. {
  79. last = carriage;
  80. carriage = carriage->next;
  81. }
  82. last->next = child;
  83. child->parent = this;
  84. return -E_SUCCESS;
  85. }
  86. int device_detach(struct device* this, struct device* child)
  87. {
  88. struct device* carriage = this->children;
  89. struct device* last = carriage;
  90. while (carriage != NULL)
  91. {
  92. if (carriage == child)
  93. {
  94. if (carriage == last)
  95. {
  96. this->children = carriage->next;
  97. return -E_SUCCESS;
  98. }
  99. else
  100. {
  101. last->next = carriage->next;
  102. carriage->next = NULL;
  103. return -E_SUCCESS;
  104. }
  105. }
  106. }
  107. return -E_NOTFOUND;
  108. }
  109. struct device*
  110. device_find_id(struct device* this, uint64_t dev_id)
  111. {
  112. if (this == NULL)
  113. return NULL;
  114. if (dev_id == this->dev_id)
  115. return this;
  116. struct device* carriage = this->children;
  117. struct device *dev = NULL;
  118. while (carriage != NULL)
  119. {
  120. if (carriage->driver == NULL)
  121. panic("Driverless attached device!");
  122. if (carriage->driver->find == NULL)
  123. panic("No find function in device!");
  124. dev = carriage->driver->find(carriage, dev_id);
  125. if (dev != NULL)
  126. return dev;
  127. carriage = carriage->next;
  128. }
  129. return NULL;
  130. }
  131. int device_id_alloc(struct device* dev)
  132. {
  133. int ret = 0;
  134. uint64_t begin = dev_id-1;
  135. mutex_lock(&dev_id_lock);
  136. struct device* iterator = device_find_id(&dev_root, dev_id);
  137. while (iterator != NULL)
  138. {
  139. dev_id++;
  140. if (dev_id == begin)
  141. panic("No more room for new devices!");
  142. iterator = device_find_id(&dev_root, dev_id);
  143. }
  144. dev->dev_id = dev_id;
  145. ret = dev_id;
  146. mutex_unlock(&dev_id_lock);
  147. return ret;
  148. }
  149. static int
  150. drv_setup_io(dev, drv, io, read, write)
  151. struct device *dev;
  152. struct driver *drv;
  153. struct vfile *io;
  154. vfs_read_hook_t read;
  155. vfs_write_hook_t write;
  156. {
  157. drv->io = io;
  158. io->uid = 0;
  159. io->gid = 0;
  160. io->read = read;
  161. io->write = write;
  162. io->type = file;
  163. return -E_SUCCESS;
  164. }
  165. int
  166. dev_setup_driver(struct device *dev, vfs_read_hook_t read, vfs_write_hook_t write)
  167. {
  168. struct driver *drv = kmalloc(sizeof(*drv));
  169. struct vfile *file = kmalloc(sizeof(*file));
  170. dev->children = NULL;
  171. dev->parent = NULL;
  172. drv_setup_io(dev,drv,file,read,write);
  173. dev->driver = drv;
  174. drv->driver_lock = 0;
  175. drv->attach_cnt.cnt = 0;
  176. drv->attach_cnt.lock = 0;
  177. /*
  178. * Setup some function pointers.
  179. */
  180. drv->attach = &device_attach;
  181. drv->detach = &device_detach;
  182. drv->resume = &device_recurse_resume;
  183. drv->suspend = &device_recurse_suspend;
  184. drv->find_type = &dev_find_devtype;
  185. drv->find = &device_find_id;
  186. return -E_SUCCESS;
  187. }
  188. struct device *
  189. dev_find_devtype(struct device *dev, device_type_t type)
  190. {
  191. if(dev != NULL)
  192. {
  193. if(dev->type == type)
  194. return dev;
  195. else
  196. {
  197. struct device *carriage;
  198. for_each_ll_entry(dev->children, carriage)
  199. {
  200. if(carriage->type == type)
  201. return carriage;
  202. if(carriage->next == NULL)
  203. return NULL;
  204. else
  205. continue;
  206. }
  207. }
  208. }
  209. return NULL;
  210. }
  211. void dev_dbg()
  212. {
  213. int i = 0;
  214. for (; i < 0x10; i++)
  215. {
  216. printf("Device 0x%X at address %X of type %X\n",
  217. i, device_find_id(&dev_root, i),
  218. device_find_id(&dev_root, i)->type
  219. );
  220. }
  221. }
  222. int
  223. dev_init()
  224. {
  225. debug("Building the device tree\n");
  226. dev_root_init();
  227. #ifdef DEV_DBG
  228. dev_dbg();
  229. #endif
  230. return -E_SUCCESS;
  231. }