bio.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* $OpenBSD: bio.c,v 1.16 2015/05/29 00:33:37 uebayasi Exp $ */
  2. /*
  3. * Copyright (c) 2002 Niklas Hallqvist. All rights reserved.
  4. * Copyright (c) 2012 Joel Sing <jsing@openbsd.org>. 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. /* A device controller ioctl tunnelling device. */
  27. #include <sys/param.h>
  28. #include <sys/device.h>
  29. #include <sys/ioctl.h>
  30. #include <sys/malloc.h>
  31. #include <sys/queue.h>
  32. #include <sys/systm.h>
  33. #include <dev/biovar.h>
  34. struct bio_mapping {
  35. LIST_ENTRY(bio_mapping) bm_link;
  36. struct device *bm_dev;
  37. int (*bm_ioctl)(struct device *, u_long, caddr_t);
  38. };
  39. LIST_HEAD(, bio_mapping) bios = LIST_HEAD_INITIALIZER(bios);
  40. void bioattach(int);
  41. int bioclose(dev_t, int, int, struct proc *);
  42. int bioioctl(dev_t, u_long, caddr_t, int, struct proc *);
  43. int bioopen(dev_t, int, int, struct proc *);
  44. int bio_delegate_ioctl(struct bio_mapping *, u_long, caddr_t);
  45. struct bio_mapping *bio_lookup(char *);
  46. int bio_validate(void *);
  47. void
  48. bioattach(int nunits)
  49. {
  50. }
  51. int
  52. bioopen(dev_t dev, int flags, int mode, struct proc *p)
  53. {
  54. return (0);
  55. }
  56. int
  57. bioclose(dev_t dev, int flags, int mode, struct proc *p)
  58. {
  59. return (0);
  60. }
  61. int
  62. bioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
  63. {
  64. struct bio_locate *locate;
  65. struct bio *bio;
  66. char name[16];
  67. int error;
  68. switch (cmd) {
  69. case BIOCLOCATE:
  70. locate = (struct bio_locate *)addr;
  71. error = copyinstr(locate->bl_name, name, sizeof name, NULL);
  72. if (error != 0)
  73. return (error);
  74. locate->bl_bio.bio_cookie = bio_lookup(name);
  75. if (locate->bl_bio.bio_cookie == NULL)
  76. return (ENOENT);
  77. break;
  78. case BIOCINQ:
  79. case BIOCDISK:
  80. case BIOCVOL:
  81. case BIOCALARM:
  82. case BIOCBLINK:
  83. case BIOCSETSTATE:
  84. case BIOCCREATERAID:
  85. case BIOCDELETERAID:
  86. case BIOCDISCIPLINE:
  87. case BIOCPATROL:
  88. bio = (struct bio *)addr;
  89. if (!bio_validate(bio->bio_cookie))
  90. return (ENOENT);
  91. return (bio_delegate_ioctl(
  92. (struct bio_mapping *)bio->bio_cookie, cmd, addr));
  93. default:
  94. return (ENXIO);
  95. }
  96. return (0);
  97. }
  98. int
  99. bio_register(struct device *dev, int (*ioctl)(struct device *, u_long, caddr_t))
  100. {
  101. struct bio_mapping *bm;
  102. bm = malloc(sizeof *bm, M_DEVBUF, M_NOWAIT);
  103. if (bm == NULL)
  104. return (ENOMEM);
  105. bm->bm_dev = dev;
  106. bm->bm_ioctl = ioctl;
  107. LIST_INSERT_HEAD(&bios, bm, bm_link);
  108. return (0);
  109. }
  110. void
  111. bio_unregister(struct device *dev)
  112. {
  113. struct bio_mapping *bm, *next;
  114. for (bm = LIST_FIRST(&bios); bm != NULL; bm = next) {
  115. next = LIST_NEXT(bm, bm_link);
  116. if (dev == bm->bm_dev) {
  117. LIST_REMOVE(bm, bm_link);
  118. free(bm, M_DEVBUF, 0);
  119. }
  120. }
  121. }
  122. struct bio_mapping *
  123. bio_lookup(char *name)
  124. {
  125. struct bio_mapping *bm;
  126. LIST_FOREACH(bm, &bios, bm_link)
  127. if (strcmp(name, bm->bm_dev->dv_xname) == 0)
  128. return (bm);
  129. return (NULL);
  130. }
  131. int
  132. bio_validate(void *cookie)
  133. {
  134. struct bio_mapping *bm;
  135. LIST_FOREACH(bm, &bios, bm_link)
  136. if (bm == cookie)
  137. return (1);
  138. return (0);
  139. }
  140. int
  141. bio_delegate_ioctl(struct bio_mapping *bm, u_long cmd, caddr_t addr)
  142. {
  143. return (bm->bm_ioctl(bm->bm_dev, cmd, addr));
  144. }
  145. void
  146. bio_info(struct bio_status *bs, int print, const char *fmt, ...)
  147. {
  148. va_list ap;
  149. va_start(ap, fmt);
  150. bio_status(bs, print, BIO_MSG_INFO, fmt, &ap);
  151. va_end(ap);
  152. }
  153. void
  154. bio_warn(struct bio_status *bs, int print, const char *fmt, ...)
  155. {
  156. va_list ap;
  157. va_start(ap, fmt);
  158. bio_status(bs, print, BIO_MSG_WARN, fmt, &ap);
  159. va_end(ap);
  160. }
  161. void
  162. bio_error(struct bio_status *bs, int print, const char *fmt, ...)
  163. {
  164. va_list ap;
  165. va_start(ap, fmt);
  166. bio_status(bs, print, BIO_MSG_ERROR, fmt, &ap);
  167. va_end(ap);
  168. }
  169. void
  170. bio_status_init(struct bio_status *bs, struct device *dv)
  171. {
  172. bzero(bs, sizeof(struct bio_status));
  173. bs->bs_status = BIO_STATUS_UNKNOWN;
  174. strlcpy(bs->bs_controller, dv->dv_xname, sizeof(bs->bs_controller));
  175. }
  176. void
  177. bio_status(struct bio_status *bs, int print, int msg_type, const char *fmt,
  178. va_list *ap)
  179. {
  180. int idx;
  181. if (bs->bs_msg_count >= BIO_MSG_COUNT) {
  182. printf("%s: insufficient message buffers\n", bs->bs_controller);
  183. return;
  184. }
  185. idx = bs->bs_msg_count++;
  186. bs->bs_msgs[idx].bm_type = msg_type;
  187. vsnprintf(bs->bs_msgs[idx].bm_msg, BIO_MSG_LEN, fmt, *ap);
  188. if (print)
  189. printf("%s: %s\n", bs->bs_controller, bs->bs_msgs[idx].bm_msg);
  190. }