com_pcmcia.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /* $OpenBSD: com_pcmcia.c,v 1.55 2015/03/14 03:38:49 jsg Exp $ */
  2. /* $NetBSD: com_pcmcia.c,v 1.15 1998/08/22 17:47:58 msaitoh Exp $ */
  3. /*
  4. * Copyright (c) 1997 - 1999, Jason Downs. 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. Neither the name(s) of the author(s) nor the name OpenBSD
  15. * may be used to endorse or promote products derived from this software
  16. * without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
  19. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
  22. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  24. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28. * SUCH DAMAGE.
  29. */
  30. /*-
  31. * Copyright (c) 1998 The NetBSD Foundation, Inc.
  32. * All rights reserved.
  33. *
  34. * This code is derived from software contributed to The NetBSD Foundation
  35. * by Charles M. Hannum.
  36. *
  37. * Redistribution and use in source and binary forms, with or without
  38. * modification, are permitted provided that the following conditions
  39. * are met:
  40. * 1. Redistributions of source code must retain the above copyright
  41. * notice, this list of conditions and the following disclaimer.
  42. * 2. Redistributions in binary form must reproduce the above copyright
  43. * notice, this list of conditions and the following disclaimer in the
  44. * documentation and/or other materials provided with the distribution.
  45. *
  46. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  47. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  48. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  49. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  50. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  51. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  52. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  53. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  54. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  55. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  56. * POSSIBILITY OF SUCH DAMAGE.
  57. */
  58. /*-
  59. * Copyright (c) 1991 The Regents of the University of California.
  60. * All rights reserved.
  61. *
  62. * Redistribution and use in source and binary forms, with or without
  63. * modification, are permitted provided that the following conditions
  64. * are met:
  65. * 1. Redistributions of source code must retain the above copyright
  66. * notice, this list of conditions and the following disclaimer.
  67. * 2. Redistributions in binary form must reproduce the above copyright
  68. * notice, this list of conditions and the following disclaimer in the
  69. * documentation and/or other materials provided with the distribution.
  70. * 3. Neither the name of the University nor the names of its contributors
  71. * may be used to endorse or promote products derived from this software
  72. * without specific prior written permission.
  73. *
  74. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  75. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  76. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  77. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  78. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  79. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  80. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  81. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  82. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  83. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  84. * SUCH DAMAGE.
  85. *
  86. * @(#)com.c 7.5 (Berkeley) 5/16/91
  87. */
  88. #include <sys/param.h>
  89. #include <sys/systm.h>
  90. #include <sys/ioctl.h>
  91. #include <sys/selinfo.h>
  92. #include <sys/tty.h>
  93. #include <sys/conf.h>
  94. #include <sys/file.h>
  95. #include <sys/uio.h>
  96. #include <sys/kernel.h>
  97. #include <sys/syslog.h>
  98. #include <sys/types.h>
  99. #include <sys/device.h>
  100. #include <machine/intr.h>
  101. #include <dev/pcmcia/pcmciavar.h>
  102. #include <dev/pcmcia/pcmciareg.h>
  103. #include <dev/pcmcia/pcmciadevs.h>
  104. #include "com.h"
  105. #include <dev/ic/comreg.h>
  106. #include <dev/ic/comvar.h>
  107. #include <dev/ic/ns16550reg.h>
  108. #include <dev/isa/isareg.h>
  109. #define com_lcr com_cfcr
  110. /* Devices that we need to match by CIS strings */
  111. struct com_pcmcia_product {
  112. char *cis1_info[4];
  113. } com_pcmcia_prod[] = {
  114. { PCMCIA_CIS_MEGAHERTZ_XJ2288 },
  115. { PCMCIA_CIS_NOVATEL_NRM6831 },
  116. };
  117. int com_pcmcia_match(struct device *, void *, void *);
  118. void com_pcmcia_attach(struct device *, struct device *, void *);
  119. int com_pcmcia_detach(struct device *, int);
  120. void com_pcmcia_cleanup(void *);
  121. int com_pcmcia_activate(struct device *, int);
  122. int com_pcmcia_enable(struct com_softc *);
  123. void com_pcmcia_disable(struct com_softc *);
  124. int com_pcmcia_enable1(struct com_softc *);
  125. void com_pcmcia_disable1(struct com_softc *);
  126. struct com_pcmcia_softc {
  127. struct com_softc sc_com; /* real "com" softc */
  128. /* PCMCIA-specific goo */
  129. struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */
  130. int sc_io_window; /* our i/o window */
  131. struct pcmcia_function *sc_pf; /* our PCMCIA function */
  132. void *sc_ih; /* interrupt handler */
  133. };
  134. struct cfattach com_pcmcia_ca = {
  135. sizeof(struct com_pcmcia_softc), com_pcmcia_match, com_pcmcia_attach,
  136. com_pcmcia_detach, com_pcmcia_activate
  137. };
  138. int
  139. com_pcmcia_match(parent, match, aux)
  140. struct device *parent;
  141. void *match, *aux;
  142. {
  143. struct pcmcia_attach_args *pa = aux;
  144. struct pcmcia_config_entry *cfe;
  145. int i, j, comportmask;
  146. /* 1. Does it claim to be a serial device? */
  147. if (pa->pf->function == PCMCIA_FUNCTION_SERIAL)
  148. return 1;
  149. /* 2. Does it have all four 'standard' port ranges? */
  150. comportmask = 0;
  151. SIMPLEQ_FOREACH(cfe, &pa->pf->cfe_head, cfe_list) {
  152. switch (cfe->iospace[0].start) {
  153. case IO_COM1:
  154. comportmask |= 1;
  155. break;
  156. case IO_COM2:
  157. comportmask |= 2;
  158. break;
  159. case IO_COM3:
  160. comportmask |= 4;
  161. break;
  162. case IO_COM4:
  163. comportmask |= 8;
  164. break;
  165. }
  166. }
  167. if (comportmask == 15)
  168. return 1;
  169. /* 3. Is this a card we know about? */
  170. for (i = 0; i < nitems(com_pcmcia_prod); i++) {
  171. for (j = 0; j < 4; j++)
  172. if (com_pcmcia_prod[i].cis1_info[j] &&
  173. pa->card->cis1_info[j] &&
  174. strcmp(pa->card->cis1_info[j],
  175. com_pcmcia_prod[i].cis1_info[j]))
  176. break;
  177. if (j == 4)
  178. return 1;
  179. }
  180. return 0;
  181. }
  182. int
  183. com_pcmcia_activate(dev, act)
  184. struct device *dev;
  185. int act;
  186. {
  187. struct com_pcmcia_softc *sc = (void *) dev;
  188. switch (act) {
  189. case DVACT_SUSPEND:
  190. if (sc->sc_ih)
  191. pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
  192. sc->sc_ih = NULL;
  193. pcmcia_function_disable(sc->sc_pf);
  194. break;
  195. case DVACT_RESUME:
  196. pcmcia_function_enable(sc->sc_pf);
  197. sc->sc_ih = pcmcia_intr_establish(sc->sc_pf, IPL_TTY,
  198. comintr, sc, sc->sc_com.sc_dev.dv_xname);
  199. com_resume(&sc->sc_com);
  200. break;
  201. case DVACT_DEACTIVATE:
  202. if (sc->sc_ih)
  203. pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih);
  204. sc->sc_ih = NULL;
  205. pcmcia_function_disable(sc->sc_pf);
  206. break;
  207. }
  208. return (0);
  209. }
  210. void
  211. com_pcmcia_attach(parent, self, aux)
  212. struct device *parent, *self;
  213. void *aux;
  214. {
  215. struct com_pcmcia_softc *psc = (void *) self;
  216. struct com_softc *sc = &psc->sc_com;
  217. struct pcmcia_attach_args *pa = aux;
  218. struct pcmcia_config_entry *cfe;
  219. const char *intrstr;
  220. int autoalloc = 0;
  221. psc->sc_pf = pa->pf;
  222. retry:
  223. /* find a cfe we can use */
  224. for (cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); cfe;
  225. cfe = SIMPLEQ_NEXT(cfe, cfe_list)) {
  226. #if 0
  227. /*
  228. * Some modem cards (e.g. Xircom CM33) also have
  229. * mem space. Don't bother with this check.
  230. */
  231. if (cfe->num_memspace != 0)
  232. continue;
  233. #endif
  234. if (cfe->num_iospace != 1)
  235. continue;
  236. if (!pcmcia_io_alloc(pa->pf,
  237. autoalloc ? 0 : cfe->iospace[0].start,
  238. cfe->iospace[0].length, COM_NPORTS, &psc->sc_pcioh)) {
  239. goto found;
  240. }
  241. }
  242. if (autoalloc == 0) {
  243. autoalloc = 1;
  244. goto retry;
  245. } else if (!cfe) {
  246. printf(": can't allocate i/o space\n");
  247. return;
  248. }
  249. found:
  250. sc->sc_iot = psc->sc_pcioh.iot;
  251. sc->sc_ioh = psc->sc_pcioh.ioh;
  252. /* Enable the card. */
  253. pcmcia_function_init(pa->pf, cfe);
  254. if (com_pcmcia_enable1(sc))
  255. printf(": function enable failed\n");
  256. sc->enabled = 1;
  257. /* map in the io space */
  258. if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ?
  259. PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, psc->sc_pcioh.size,
  260. &psc->sc_pcioh, &psc->sc_io_window)) {
  261. printf(": can't map i/o space\n");
  262. return;
  263. }
  264. printf(" port 0x%lx/%lu", psc->sc_pcioh.addr,
  265. (u_long)psc->sc_pcioh.size);
  266. sc->sc_iobase = -1;
  267. sc->enable = com_pcmcia_enable;
  268. sc->disable = com_pcmcia_disable;
  269. sc->sc_frequency = COM_FREQ;
  270. sc->sc_hwflags = 0;
  271. sc->sc_swflags = 0;
  272. if (psc->sc_pf->sc->card.manufacturer == PCMCIA_VENDOR_AUDIOVOX &&
  273. psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_AUDIOVOX_RTM8000)
  274. sc->sc_fifolen = 16;
  275. com_attach_subr(sc);
  276. /* establish the interrupt. */
  277. psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_TTY, comintr, sc,
  278. sc->sc_dev.dv_xname);
  279. intrstr = pcmcia_intr_string(psc->sc_pf, psc->sc_ih);
  280. if (*intrstr)
  281. printf(", %s", intrstr);
  282. #ifdef notyet
  283. sc->enabled = 0;
  284. com_pcmcia_disable1(sc);
  285. #endif
  286. }
  287. int
  288. com_pcmcia_detach(dev, flags)
  289. struct device *dev;
  290. int flags;
  291. {
  292. struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *)dev;
  293. int error;
  294. /* Release all resources. */
  295. error = com_detach(dev, flags);
  296. if (error)
  297. return (error);
  298. pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window);
  299. pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh);
  300. return (0);
  301. }
  302. int
  303. com_pcmcia_enable(sc)
  304. struct com_softc *sc;
  305. {
  306. struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
  307. struct pcmcia_function *pf = psc->sc_pf;
  308. /* establish the interrupt. */
  309. psc->sc_ih = pcmcia_intr_establish(pf, IPL_TTY, comintr, sc,
  310. sc->sc_dev.dv_xname);
  311. if (psc->sc_ih == NULL) {
  312. printf("%s: couldn't establish interrupt\n",
  313. sc->sc_dev.dv_xname);
  314. return (1);
  315. }
  316. return com_pcmcia_enable1(sc);
  317. }
  318. int
  319. com_pcmcia_enable1(sc)
  320. struct com_softc *sc;
  321. {
  322. struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
  323. struct pcmcia_function *pf = psc->sc_pf;
  324. int ret;
  325. if ((ret = pcmcia_function_enable(pf)))
  326. return(ret);
  327. if ((psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3C562) ||
  328. (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556) ||
  329. (psc->sc_pf->sc->card.product == PCMCIA_PRODUCT_3COM_3CXEM556B)) {
  330. int reg;
  331. /* turn off the ethernet-disable bit */
  332. reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
  333. if (reg & 0x08) {
  334. reg &= ~0x08;
  335. pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
  336. }
  337. }
  338. return(ret);
  339. }
  340. void
  341. com_pcmcia_disable(sc)
  342. struct com_softc *sc;
  343. {
  344. struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
  345. pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih);
  346. com_pcmcia_disable1(sc);
  347. }
  348. void
  349. com_pcmcia_disable1(sc)
  350. struct com_softc *sc;
  351. {
  352. struct com_pcmcia_softc *psc = (struct com_pcmcia_softc *) sc;
  353. pcmcia_function_disable(psc->sc_pf);
  354. }