mambo_disk.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (c) 2008 Nathan Whitehorn. All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. *
  15. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  16. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  17. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  18. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  19. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  21. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  22. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. *
  26. */
  27. #include <sys/cdefs.h>
  28. __FBSDID("$FreeBSD$");
  29. #include <sys/param.h>
  30. #include <sys/systm.h>
  31. #include <sys/bio.h>
  32. #include <sys/bus.h>
  33. #include <sys/conf.h>
  34. #include <sys/kernel.h>
  35. #include <sys/kthread.h>
  36. #include <sys/lock.h>
  37. #include <sys/malloc.h>
  38. #include <sys/module.h>
  39. #include <sys/mutex.h>
  40. #include <geom/geom_disk.h>
  41. #include <powerpc/mambo/mambocall.h>
  42. struct mambodisk_softc {
  43. device_t dev;
  44. struct mtx sc_mtx;
  45. struct disk *disk;
  46. struct proc *p;
  47. struct bio_queue_head bio_queue;
  48. int running;
  49. int maxblocks;
  50. };
  51. #define MAMBO_DISK_READ 116
  52. #define MAMBO_DISK_WRITE 117
  53. #define MAMBO_DISK_INFO 118
  54. #define MAMBO_INFO_STATUS 1
  55. #define MAMBO_INFO_BLKSZ 2
  56. #define MAMBO_INFO_DEVSZ 3
  57. /* bus entry points */
  58. static void mambodisk_identify(driver_t *driver, device_t parent);
  59. static int mambodisk_probe(device_t dev);
  60. static int mambodisk_attach(device_t dev);
  61. /* disk routines */
  62. static int mambodisk_open(struct disk *dp);
  63. static int mambodisk_close(struct disk *dp);
  64. static void mambodisk_strategy(struct bio *bp);
  65. static void mambodisk_task(void *arg);
  66. #define MBODISK_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
  67. #define MBODISK_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx)
  68. #define MBODISK_LOCK_INIT(_sc) \
  69. mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
  70. "mambodisk", MTX_DEF)
  71. #define MBODISK_LOCK_DESTROY(_sc) mtx_destroy(&_sc->sc_mtx);
  72. #define MBODISK_ASSERT_LOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_OWNED);
  73. #define MBODISK_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
  74. static void
  75. mambodisk_identify(driver_t *driver, device_t parent)
  76. {
  77. int i = 0;
  78. for (i = 0; mambocall(MAMBO_DISK_INFO,MAMBO_INFO_DEVSZ,i) > 0; i++)
  79. BUS_ADD_CHILD(parent,0,"mambodisk",i);
  80. }
  81. static int
  82. mambodisk_probe(device_t dev)
  83. {
  84. device_set_desc(dev, "Mambo Simulated Block Device");
  85. return (0);
  86. }
  87. static int
  88. mambodisk_attach(device_t dev)
  89. {
  90. struct mambodisk_softc *sc;
  91. struct disk *d;
  92. intmax_t mb;
  93. char unit;
  94. sc = device_get_softc(dev);
  95. sc->dev = dev;
  96. MBODISK_LOCK_INIT(sc);
  97. d = sc->disk = disk_alloc();
  98. d->d_open = mambodisk_open;
  99. d->d_close = mambodisk_close;
  100. d->d_strategy = mambodisk_strategy;
  101. d->d_name = "mambodisk";
  102. d->d_drv1 = sc;
  103. d->d_maxsize = maxphys; /* Maybe ask bridge? */
  104. d->d_sectorsize = 512;
  105. sc->maxblocks = mambocall(MAMBO_DISK_INFO,MAMBO_INFO_BLKSZ,d->d_unit)
  106. / 512;
  107. d->d_unit = device_get_unit(dev);
  108. d->d_mediasize = mambocall(MAMBO_DISK_INFO,MAMBO_INFO_DEVSZ,d->d_unit)
  109. * 1024ULL; /* Mambo gives size in KB */
  110. mb = d->d_mediasize >> 20; /* 1MiB == 1 << 20 */
  111. unit = 'M';
  112. if (mb >= 10240) { /* 1GiB = 1024 MiB */
  113. unit = 'G';
  114. mb /= 1024;
  115. }
  116. device_printf(dev, "%ju%cB, %d byte sectors\n", mb, unit,
  117. d->d_sectorsize);
  118. disk_create(d, DISK_VERSION);
  119. bioq_init(&sc->bio_queue);
  120. sc->running = 1;
  121. kproc_create(&mambodisk_task, sc, &sc->p, 0, 0, "task: mambo hd");
  122. return (0);
  123. }
  124. static int
  125. mambodisk_detach(device_t dev)
  126. {
  127. struct mambodisk_softc *sc = device_get_softc(dev);
  128. /* kill thread */
  129. MBODISK_LOCK(sc);
  130. sc->running = 0;
  131. wakeup(sc);
  132. MBODISK_UNLOCK(sc);
  133. /* wait for thread to finish. XXX probably want timeout. -sorbo */
  134. MBODISK_LOCK(sc);
  135. while (sc->running != -1)
  136. msleep(sc, &sc->sc_mtx, PRIBIO, "detach", 0);
  137. MBODISK_UNLOCK(sc);
  138. /* kill disk */
  139. disk_destroy(sc->disk);
  140. /* XXX destroy anything in queue */
  141. MBODISK_LOCK_DESTROY(sc);
  142. return (0);
  143. }
  144. static int
  145. mambodisk_open(struct disk *dp)
  146. {
  147. return (0);
  148. }
  149. static int
  150. mambodisk_close(struct disk *dp)
  151. {
  152. return (0);
  153. }
  154. static void
  155. mambodisk_strategy(struct bio *bp)
  156. {
  157. struct mambodisk_softc *sc;
  158. sc = (struct mambodisk_softc *)bp->bio_disk->d_drv1;
  159. MBODISK_LOCK(sc);
  160. bioq_disksort(&sc->bio_queue, bp);
  161. wakeup(sc);
  162. MBODISK_UNLOCK(sc);
  163. }
  164. static void
  165. mambodisk_task(void *arg)
  166. {
  167. struct mambodisk_softc *sc = (struct mambodisk_softc*)arg;
  168. struct bio *bp;
  169. size_t sz;
  170. int result;
  171. daddr_t block, end;
  172. device_t dev;
  173. u_long unit;
  174. dev = sc->dev;
  175. unit = device_get_unit(dev);
  176. while (sc->running) {
  177. MBODISK_LOCK(sc);
  178. do {
  179. bp = bioq_first(&sc->bio_queue);
  180. if (bp == NULL)
  181. msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
  182. } while (bp == NULL && sc->running);
  183. if (bp)
  184. bioq_remove(&sc->bio_queue, bp);
  185. MBODISK_UNLOCK(sc);
  186. if (!sc->running)
  187. break;
  188. sz = sc->disk->d_sectorsize;
  189. end = bp->bio_pblkno + (bp->bio_bcount / sz);
  190. for (block = bp->bio_pblkno; block < end;) {
  191. u_long numblocks;
  192. char *vaddr = bp->bio_data +
  193. (block - bp->bio_pblkno) * sz;
  194. numblocks = end - block;
  195. if (numblocks > sc->maxblocks)
  196. numblocks = sc->maxblocks;
  197. if (bp->bio_cmd == BIO_READ) {
  198. result = mambocall(MAMBO_DISK_READ, vaddr,
  199. (u_long)block, (numblocks << 16) | unit);
  200. } else if (bp->bio_cmd == BIO_WRITE) {
  201. result = mambocall(MAMBO_DISK_WRITE, vaddr,
  202. (u_long)block, (numblocks << 16) | unit);
  203. } else {
  204. result = 1;
  205. }
  206. if (result)
  207. break;
  208. block += numblocks;
  209. }
  210. if (block < end) {
  211. bp->bio_error = EIO;
  212. bp->bio_resid = (end - block) * sz;
  213. bp->bio_flags |= BIO_ERROR;
  214. }
  215. biodone(bp);
  216. }
  217. /* tell parent we're done */
  218. MBODISK_LOCK(sc);
  219. sc->running = -1;
  220. wakeup(sc);
  221. MBODISK_UNLOCK(sc);
  222. kproc_exit(0);
  223. }
  224. static device_method_t mambodisk_methods[] = {
  225. DEVMETHOD(device_identify, mambodisk_identify),
  226. DEVMETHOD(device_probe, mambodisk_probe),
  227. DEVMETHOD(device_attach, mambodisk_attach),
  228. DEVMETHOD(device_detach, mambodisk_detach),
  229. {0, 0},
  230. };
  231. static driver_t mambodisk_driver = {
  232. "mambodisk",
  233. mambodisk_methods,
  234. sizeof(struct mambodisk_softc),
  235. };
  236. static devclass_t mambodisk_devclass;
  237. DRIVER_MODULE(mambodisk, mambo, mambodisk_driver, mambodisk_devclass, 0, 0);