pcmcia_cis_quirks.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /* $OpenBSD: pcmcia_cis_quirks.c,v 1.12 2015/03/14 03:38:49 jsg Exp $ */
  2. /* $NetBSD: pcmcia_cis_quirks.c,v 1.3 1998/12/29 09:00:28 marc Exp $ */
  3. /*
  4. * Copyright (c) 1998 Marc Horowitz. 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. * 3. All advertising materials mentioning features or use of this software
  15. * must display the following acknowledgement:
  16. * This product includes software developed by Marc Horowitz.
  17. * 4. The name of the author may not be used to endorse or promote products
  18. * derived from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  21. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  22. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  23. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  24. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  29. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include <sys/types.h>
  32. #include <sys/param.h>
  33. #include <sys/systm.h>
  34. #include <sys/malloc.h>
  35. #include <sys/device.h>
  36. #include <dev/pcmcia/pcmciadevs.h>
  37. #include <dev/pcmcia/pcmciareg.h>
  38. #include <dev/pcmcia/pcmciavar.h>
  39. /* There are cards out there whose CIS flat-out lies. This file
  40. contains struct pcmcia_function chains for those devices. */
  41. /* these structures are just static templates which are then copied
  42. into "live" allocated structures */
  43. struct pcmcia_function pcmcia_3cxem556_func0 = {
  44. 0, /* function number */
  45. PCMCIA_FUNCTION_NETWORK,
  46. 0x07, /* last cfe number */
  47. 0x800, /* ccr_base */
  48. 0x63, /* ccr_mask */
  49. };
  50. struct pcmcia_config_entry pcmcia_3cxem556_func0_cfe0 = {
  51. 0x07, /* cfe number */
  52. PCMCIA_CFE_IO8 | PCMCIA_CFE_IO16 | PCMCIA_CFE_IRQLEVEL,
  53. PCMCIA_IFTYPE_IO,
  54. 1, /* num_iospace */
  55. 4, /* iomask */
  56. { { 0x0010, 0 } }, /* iospace */
  57. 0xffff, /* irqmask */
  58. 0, /* num_memspace */
  59. { }, /* memspace */
  60. 0, /* maxtwins */
  61. };
  62. static struct pcmcia_function pcmcia_3cxem556_func1 = {
  63. 1, /* function number */
  64. PCMCIA_FUNCTION_SERIAL,
  65. 0x27, /* last cfe number */
  66. 0x900, /* ccr_base */
  67. 0x63, /* ccr_mask */
  68. };
  69. static struct pcmcia_config_entry pcmcia_3cxem556_func1_cfe0 = {
  70. 0x27, /* cfe number */
  71. PCMCIA_CFE_IO8 | PCMCIA_CFE_IRQLEVEL,
  72. PCMCIA_IFTYPE_IO,
  73. 1, /* num_iospace */
  74. 3, /* iomask */
  75. { { 0x0008, 0 } }, /* iospace */
  76. 0xffff, /* irqmask */
  77. 0, /* num_memspace */
  78. { }, /* memspace */
  79. 0, /* maxtwins */
  80. };
  81. struct pcmcia_function pcmcia_megahertz_xjem1144_func0 = {
  82. 0, /* function number */
  83. PCMCIA_FUNCTION_NETWORK,
  84. 0x07, /* last cfe number */
  85. 0x200, /* ccr_base */
  86. 0x63, /* ccr_mask */
  87. };
  88. struct pcmcia_config_entry pcmcia_megahertz_xjem1144_func0_cfe0 = {
  89. 0x07, /* cfe number */
  90. PCMCIA_CFE_IO8 | PCMCIA_CFE_IO16 | PCMCIA_CFE_IRQLEVEL,
  91. PCMCIA_IFTYPE_IO,
  92. 1, /* num_iospace */
  93. 4, /* iomask */
  94. { { 0x0010, 0 } }, /* iospace */
  95. 0xffff, /* irqmask */
  96. 0, /* num_memspace */
  97. { }, /* memspace */
  98. 0, /* maxtwins */
  99. };
  100. static struct pcmcia_function pcmcia_megahertz_xjem1144_func1 = {
  101. 1, /* function number */
  102. PCMCIA_FUNCTION_SERIAL,
  103. 0x35, /* last cfe number */
  104. 0x300, /* ccr_base */
  105. 0x3, /* ccr_mask */
  106. };
  107. static struct pcmcia_config_entry pcmcia_megahertz_xjem1144_func1_cfe0 = {
  108. 0x35, /* cfe number */
  109. PCMCIA_CFE_IO8 | PCMCIA_CFE_IRQLEVEL, PCMCIA_IFTYPE_IO,
  110. 1, /* num_iospace */
  111. 0, /* iomask */
  112. { { 0x0008, 0x2f8 } }, /* iospace */
  113. 0xffff, /* irqmask */
  114. 0, /* num_memspace */
  115. { }, /* memspace */
  116. 0, /* maxtwins */
  117. };
  118. static struct pcmcia_function pcmcia_sierra_a555_func1 = {
  119. 1, /* function number */
  120. PCMCIA_FUNCTION_SERIAL,
  121. 0x24, /* last cfe number */
  122. 0x700, /* ccr_base */
  123. 0x73, /* ccr_mask */
  124. };
  125. static struct pcmcia_config_entry pcmcia_sierra_a555_func1_cfe0 = {
  126. 0x20, /* cfe number */
  127. PCMCIA_CFE_IO8 | PCMCIA_CFE_IRQLEVEL, PCMCIA_IFTYPE_IO,
  128. 1, /* num_iospace */
  129. 0, /* iomask */
  130. { { 0x0008, 0x3f8 } }, /* iospace */
  131. 0x3fbc, /* irqmask */
  132. 0, /* num_memspace */
  133. { }, /* memspace */
  134. 0, /* maxtwins */
  135. };
  136. static struct pcmcia_function pcmcia_sveclancard_func0 = {
  137. 0, /* function number */
  138. PCMCIA_FUNCTION_NETWORK,
  139. 0x1, /* last cfe number */
  140. 0x100, /* ccr_base */
  141. 0x1, /* ccr_mask */
  142. };
  143. static struct pcmcia_config_entry pcmcia_sveclancard_func0_cfe0 = {
  144. 0x1, /* cfe number */
  145. PCMCIA_CFE_MWAIT_REQUIRED | PCMCIA_CFE_RDYBSY_ACTIVE |
  146. PCMCIA_CFE_WP_ACTIVE | PCMCIA_CFE_BVD_ACTIVE | PCMCIA_CFE_IO16,
  147. PCMCIA_IFTYPE_IO,
  148. 1, /* num_iospace */
  149. 5, /* iomask */
  150. { { 0x20, 0x300 } }, /* iospace */
  151. 0xdeb8, /* irqmask */
  152. 0, /* num_memspace */
  153. { }, /* memspace */
  154. 0, /* maxtwins */
  155. };
  156. static struct pcmcia_cis_quirk pcmcia_cis_quirks[] = {
  157. { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556, PCMCIA_CIS_INVALID,
  158. &pcmcia_3cxem556_func0, &pcmcia_3cxem556_func0_cfe0 },
  159. { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556, PCMCIA_CIS_INVALID,
  160. &pcmcia_3cxem556_func1, &pcmcia_3cxem556_func1_cfe0 },
  161. { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556B,
  162. PCMCIA_CIS_INVALID,
  163. &pcmcia_3cxem556_func0, &pcmcia_3cxem556_func0_cfe0 },
  164. { PCMCIA_VENDOR_3COM, PCMCIA_PRODUCT_3COM_3CXEM556B,
  165. PCMCIA_CIS_INVALID,
  166. &pcmcia_3cxem556_func1, &pcmcia_3cxem556_func1_cfe0 },
  167. { PCMCIA_VENDOR_MEGAHERTZ2, PCMCIA_PRODUCT_MEGAHERTZ2_XJEM1144,
  168. PCMCIA_CIS_INVALID,
  169. &pcmcia_megahertz_xjem1144_func0,
  170. &pcmcia_megahertz_xjem1144_func0_cfe0 },
  171. { PCMCIA_VENDOR_MEGAHERTZ2, PCMCIA_PRODUCT_MEGAHERTZ2_XJEM1144,
  172. PCMCIA_CIS_INVALID,
  173. &pcmcia_megahertz_xjem1144_func1,
  174. &pcmcia_megahertz_xjem1144_func1_cfe0 },
  175. { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_A550,
  176. PCMCIA_CIS_INVALID,
  177. &pcmcia_sierra_a555_func1, &pcmcia_sierra_a555_func1_cfe0 },
  178. { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_A555,
  179. PCMCIA_CIS_INVALID,
  180. &pcmcia_sierra_a555_func1, &pcmcia_sierra_a555_func1_cfe0 },
  181. { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_A710,
  182. PCMCIA_CIS_INVALID,
  183. &pcmcia_sierra_a555_func1, &pcmcia_sierra_a555_func1_cfe0 },
  184. { PCMCIA_VENDOR_SIERRA, PCMCIA_PRODUCT_SIERRA_AC710,
  185. PCMCIA_CIS_INVALID,
  186. &pcmcia_sierra_a555_func1, &pcmcia_sierra_a555_func1_cfe0 },
  187. { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID,
  188. PCMCIA_CIS_SVEC_LANCARD,
  189. &pcmcia_sveclancard_func0, &pcmcia_sveclancard_func0_cfe0 },
  190. };
  191. void pcmcia_check_cis_quirks(sc)
  192. struct pcmcia_softc *sc;
  193. {
  194. int wiped = 0;
  195. int i, j;
  196. struct pcmcia_function *pf, *pf_next, *pf_last;
  197. struct pcmcia_config_entry *cfe, *cfe_next;
  198. pf = NULL;
  199. pf_last = NULL;
  200. for (i = 0; i < nitems(pcmcia_cis_quirks);
  201. i++) {
  202. if ((sc->card.manufacturer == pcmcia_cis_quirks[i].manufacturer) &&
  203. (sc->card.product == pcmcia_cis_quirks[i].product) &&
  204. (((sc->card.manufacturer != PCMCIA_VENDOR_INVALID) &&
  205. (sc->card.product != PCMCIA_PRODUCT_INVALID)) ||
  206. ((sc->card.manufacturer == PCMCIA_VENDOR_INVALID) &&
  207. (sc->card.product == PCMCIA_PRODUCT_INVALID) &&
  208. sc->card.cis1_info[0] &&
  209. (strcmp(sc->card.cis1_info[0],
  210. pcmcia_cis_quirks[i].cis1_info[0]) == 0) &&
  211. sc->card.cis1_info[1] &&
  212. (strcmp(sc->card.cis1_info[1],
  213. pcmcia_cis_quirks[i].cis1_info[1]) == 0)))) {
  214. if (!wiped) {
  215. if (pcmcia_verbose) {
  216. printf("%s: using CIS quirks for ", sc->dev.dv_xname);
  217. for (j = 0; j < 4; j++) {
  218. if (sc->card.cis1_info[j] == NULL)
  219. break;
  220. if (j)
  221. printf(", ");
  222. printf("%s", sc->card.cis1_info[j]);
  223. }
  224. printf("\n");
  225. }
  226. for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  227. pf = pf_next) {
  228. for (cfe = SIMPLEQ_FIRST(&pf->cfe_head); cfe != NULL;
  229. cfe = cfe_next) {
  230. cfe_next = SIMPLEQ_NEXT(cfe, cfe_list);
  231. free(cfe, M_DEVBUF, 0);
  232. }
  233. pf_next = SIMPLEQ_NEXT(pf, pf_list);
  234. free(pf, M_DEVBUF, 0);
  235. }
  236. SIMPLEQ_INIT(&sc->card.pf_head);
  237. wiped = 1;
  238. }
  239. if (pf_last == pcmcia_cis_quirks[i].pf) {
  240. cfe = malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
  241. if (cfe == NULL)
  242. return;
  243. *cfe = *pcmcia_cis_quirks[i].cfe;
  244. SIMPLEQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
  245. } else {
  246. pf = malloc(sizeof(*pf), M_DEVBUF, M_NOWAIT);
  247. if (pf == NULL)
  248. return;
  249. *pf = *pcmcia_cis_quirks[i].pf;
  250. SIMPLEQ_INIT(&pf->cfe_head);
  251. cfe = malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
  252. if (cfe == NULL)
  253. return;
  254. *cfe = *pcmcia_cis_quirks[i].cfe;
  255. SIMPLEQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
  256. SIMPLEQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
  257. pf_last = pcmcia_cis_quirks[i].pf;
  258. }
  259. }
  260. }
  261. }