pcmcia.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921
  1. /* $OpenBSD: pcmcia.c,v 1.46 2012/10/08 21:47:50 deraadt Exp $ */
  2. /* $NetBSD: pcmcia.c,v 1.9 1998/08/13 02:10:55 eeh Exp $ */
  3. /*
  4. * Copyright (c) 1997 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/device.h>
  35. #include <sys/malloc.h>
  36. #include <dev/pcmcia/pcmciareg.h>
  37. #include <dev/pcmcia/pcmciachip.h>
  38. #include <dev/pcmcia/pcmciavar.h>
  39. #ifdef PCMCIADEBUG
  40. #define DPRINTF(arg) printf arg
  41. #else
  42. #define DPRINTF(arg)
  43. #endif
  44. #ifdef PCMCIAVERBOSE
  45. int pcmcia_verbose = 1;
  46. #else
  47. int pcmcia_verbose = 0;
  48. #endif
  49. int pcmcia_match(struct device *, void *, void *);
  50. int pcmcia_submatch(struct device *, void *, void *);
  51. void pcmcia_attach(struct device *, struct device *, void *);
  52. int pcmcia_activate(struct device *, int);
  53. int pcmcia_print(void *, const char *);
  54. void pcmcia_card_detach_notify(struct device *, void *);
  55. static inline void pcmcia_socket_enable(pcmcia_chipset_tag_t,
  56. pcmcia_chipset_handle_t *);
  57. static inline void pcmcia_socket_disable(pcmcia_chipset_tag_t,
  58. pcmcia_chipset_handle_t *);
  59. int pcmcia_card_intr(void *);
  60. struct cfdriver pcmcia_cd = {
  61. NULL, "pcmcia", DV_DULL
  62. };
  63. struct cfattach pcmcia_ca = {
  64. sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach, NULL,
  65. pcmcia_activate
  66. };
  67. int
  68. pcmcia_ccr_read(pf, ccr)
  69. struct pcmcia_function *pf;
  70. int ccr;
  71. {
  72. return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
  73. pf->pf_ccr_offset + ccr));
  74. }
  75. void
  76. pcmcia_ccr_write(pf, ccr, val)
  77. struct pcmcia_function *pf;
  78. int ccr;
  79. int val;
  80. {
  81. if ((pf->ccr_mask) & (1 << (ccr / 2))) {
  82. bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
  83. pf->pf_ccr_offset + ccr, val);
  84. }
  85. }
  86. int
  87. pcmcia_match(parent, match, aux)
  88. struct device *parent;
  89. void *match, *aux;
  90. {
  91. struct cfdata *cf = match;
  92. struct pcmciabus_attach_args *paa = aux;
  93. if (strcmp(paa->paa_busname, cf->cf_driver->cd_name))
  94. return 0;
  95. /* If the autoconfiguration got this far, there's a socket here. */
  96. return (1);
  97. }
  98. void
  99. pcmcia_attach(parent, self, aux)
  100. struct device *parent, *self;
  101. void *aux;
  102. {
  103. struct pcmciabus_attach_args *paa = aux;
  104. struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
  105. printf("\n");
  106. sc->pct = paa->pct;
  107. sc->pch = paa->pch;
  108. sc->iobase = paa->iobase;
  109. sc->iosize = paa->iosize;
  110. sc->ih = NULL;
  111. }
  112. int
  113. pcmcia_activate(struct device *self, int act)
  114. {
  115. struct pcmcia_softc *sc = (struct pcmcia_softc *)self;
  116. struct pcmcia_function *pf;
  117. switch (act) {
  118. case DVACT_QUIESCE:
  119. case DVACT_SUSPEND:
  120. case DVACT_POWERDOWN:
  121. case DVACT_RESUME:
  122. for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  123. pf = SIMPLEQ_NEXT(pf, pf_list)) {
  124. if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL ||
  125. pf->child == NULL)
  126. continue;
  127. config_suspend(pf->child, act);
  128. }
  129. break;
  130. case DVACT_DEACTIVATE:
  131. for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  132. pf = SIMPLEQ_NEXT(pf, pf_list)) {
  133. if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL ||
  134. pf->child == NULL)
  135. continue;
  136. config_deactivate(pf->child);
  137. }
  138. break;
  139. }
  140. return (0);
  141. }
  142. int
  143. pcmcia_card_attach(dev)
  144. struct device *dev;
  145. {
  146. struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
  147. struct pcmcia_function *pf;
  148. struct pcmcia_attach_args paa;
  149. int attached;
  150. /*
  151. * this is here so that when socket_enable calls gettype, trt happens
  152. */
  153. SIMPLEQ_FIRST(&sc->card.pf_head) = NULL;
  154. pcmcia_chip_socket_enable(sc->pct, sc->pch);
  155. pcmcia_read_cis(sc);
  156. pcmcia_chip_socket_disable(sc->pct, sc->pch);
  157. pcmcia_check_cis_quirks(sc);
  158. /*
  159. * Bail now if there was an error in the CIS.
  160. */
  161. if (sc->card.error)
  162. return (1);
  163. #if 0
  164. if (SIMPLEQ_EMPTY(&sc->card.pf_head))
  165. return (1);
  166. #endif
  167. if (pcmcia_verbose)
  168. pcmcia_print_cis(sc);
  169. /*
  170. * If there was no function, this might be CIS-less card we still
  171. * want to probe. Fixup a function element for it.
  172. */
  173. if (SIMPLEQ_FIRST(&sc->card.pf_head) == NULL) {
  174. pf = malloc(sizeof *pf, M_DEVBUF, M_NOWAIT | M_ZERO);
  175. if (pf == NULL)
  176. panic("pcmcia_card_attach");
  177. pf->number = 0;
  178. pf->pf_flags = PFF_FAKE;
  179. pf->last_config_index = -1;
  180. SIMPLEQ_INIT(&pf->cfe_head);
  181. SIMPLEQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
  182. }
  183. attached = 0;
  184. for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  185. pf = SIMPLEQ_NEXT(pf, pf_list)) {
  186. pf->sc = sc;
  187. pf->child = NULL;
  188. pf->cfe = NULL;
  189. pf->ih_fct = NULL;
  190. pf->ih_arg = NULL;
  191. }
  192. for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  193. pf = SIMPLEQ_NEXT(pf, pf_list)) {
  194. paa.manufacturer = sc->card.manufacturer;
  195. paa.product = sc->card.product;
  196. paa.card = &sc->card;
  197. paa.pf = pf;
  198. pf->child = config_found_sm(&sc->dev, &paa, pcmcia_print,
  199. pcmcia_submatch);
  200. if (pf->child) {
  201. attached++;
  202. if ((pf->pf_flags & (PFF_FAKE | PFF_ENABLED)) ==
  203. PFF_ENABLED)
  204. DPRINTF(("%s: function %d CCR at %d offset %lx"
  205. ": %x %x %x %x, %x %x %x %x, %x\n",
  206. sc->dev.dv_xname, pf->number,
  207. pf->pf_ccr_window, pf->pf_ccr_offset,
  208. pcmcia_ccr_read(pf, 0x00),
  209. pcmcia_ccr_read(pf, 0x02),
  210. pcmcia_ccr_read(pf, 0x04),
  211. pcmcia_ccr_read(pf, 0x06),
  212. pcmcia_ccr_read(pf, 0x0A),
  213. pcmcia_ccr_read(pf, 0x0C),
  214. pcmcia_ccr_read(pf, 0x0E),
  215. pcmcia_ccr_read(pf, 0x10),
  216. pcmcia_ccr_read(pf, 0x12)));
  217. }
  218. }
  219. return (attached ? 0 : 1);
  220. }
  221. void
  222. pcmcia_card_detach(dev, flags)
  223. struct device *dev;
  224. int flags; /* DETACH_* flags */
  225. {
  226. struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
  227. struct pcmcia_function *pf;
  228. int error;
  229. /*
  230. * We are running on either the PCMCIA socket's event thread
  231. * or in user context detaching a device by user request.
  232. */
  233. for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  234. pf = SIMPLEQ_NEXT(pf, pf_list)) {
  235. if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
  236. continue;
  237. if (pf->child == NULL)
  238. continue;
  239. DPRINTF(("%s: detaching %s (function %d)\n",
  240. sc->dev.dv_xname, pf->child->dv_xname, pf->number));
  241. if ((error = config_detach(pf->child, flags)) != 0) {
  242. printf("%s: error %d detaching %s (function %d)\n",
  243. sc->dev.dv_xname, error, pf->child->dv_xname,
  244. pf->number);
  245. } else
  246. pf->child = NULL;
  247. }
  248. }
  249. void
  250. pcmcia_card_deactivate(dev)
  251. struct device *dev;
  252. {
  253. struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
  254. struct pcmcia_function *pf;
  255. /*
  256. * We're in the chip's card removal interrupt handler.
  257. * Deactivate the child driver. The PCMCIA socket's
  258. * event thread will run later to finish the detach.
  259. */
  260. for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  261. pf = SIMPLEQ_NEXT(pf, pf_list)) {
  262. if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL ||
  263. pf->child == NULL)
  264. continue;
  265. DPRINTF(("%s: deactivating %s (function %d)\n",
  266. sc->dev.dv_xname, pf->child->dv_xname, pf->number));
  267. config_deactivate(pf->child);
  268. }
  269. }
  270. int
  271. pcmcia_submatch(parent, match, aux)
  272. struct device *parent;
  273. void *match, *aux;
  274. {
  275. struct cfdata *cf = match;
  276. struct pcmcia_attach_args *paa = aux;
  277. if (cf->cf_loc[0 /* PCMCIACF_FUNCTION */] !=
  278. -1 /* PCMCIACF_FUNCTION_DEFAULT */ &&
  279. cf->cf_loc[0 /* PCMCIACF_FUNCTION */] != paa->pf->number)
  280. return (0);
  281. return ((*cf->cf_attach->ca_match)(parent, cf, aux));
  282. }
  283. int
  284. pcmcia_print(arg, pnp)
  285. void *arg;
  286. const char *pnp;
  287. {
  288. struct pcmcia_attach_args *pa = arg;
  289. struct pcmcia_softc *sc = pa->pf->sc;
  290. struct pcmcia_card *card = &sc->card;
  291. int i;
  292. if (pnp) {
  293. for (i = 0; i < 4 && card->cis1_info[i]; i++)
  294. printf("%s%s", i ? ", " : "\"", card->cis1_info[i]);
  295. if (i != 0)
  296. printf("\"");
  297. if (card->manufacturer != PCMCIA_VENDOR_INVALID &&
  298. card->product != PCMCIA_PRODUCT_INVALID) {
  299. if (i != 0)
  300. printf(" ");
  301. printf("(");
  302. if (card->manufacturer != PCMCIA_VENDOR_INVALID)
  303. printf("manufacturer 0x%x%s",
  304. card->manufacturer,
  305. card->product == PCMCIA_PRODUCT_INVALID ?
  306. "" : ", ");
  307. if (card->product != PCMCIA_PRODUCT_INVALID)
  308. printf("product 0x%x",
  309. card->product);
  310. printf(")");
  311. }
  312. if (i != 0)
  313. printf(" ");
  314. printf("at %s", pnp);
  315. }
  316. printf(" function %d", pa->pf->number);
  317. if (!pnp) {
  318. for (i = 0; i < 3 && card->cis1_info[i]; i++)
  319. printf("%s%s", i ? ", " : " \"", card->cis1_info[i]);
  320. if (i != 0)
  321. printf("\"");
  322. }
  323. return (UNCONF);
  324. }
  325. int
  326. pcmcia_card_gettype(dev)
  327. struct device *dev;
  328. {
  329. struct pcmcia_softc *sc = (struct pcmcia_softc *)dev;
  330. struct pcmcia_function *pf;
  331. /*
  332. * Set the iftype to memory if this card has no functions (not yet
  333. * probed), or only one function, and that is not initialized yet or
  334. * that is memory.
  335. */
  336. pf = SIMPLEQ_FIRST(&sc->card.pf_head);
  337. if (pf == NULL || (SIMPLEQ_NEXT(pf, pf_list) == NULL &&
  338. ((pf->pf_flags & PFF_FAKE) ||
  339. pf->cfe == NULL || pf->cfe->iftype == PCMCIA_IFTYPE_MEMORY)))
  340. return (PCMCIA_IFTYPE_MEMORY);
  341. else
  342. return (PCMCIA_IFTYPE_IO);
  343. }
  344. /*
  345. * Initialize a PCMCIA function. May be called as long as the function is
  346. * disabled.
  347. */
  348. void
  349. pcmcia_function_init(pf, cfe)
  350. struct pcmcia_function *pf;
  351. struct pcmcia_config_entry *cfe;
  352. {
  353. if (pf->pf_flags & PFF_ENABLED)
  354. panic("pcmcia_function_init: function is enabled");
  355. /* Remember which configuration entry we are using. */
  356. pf->cfe = cfe;
  357. }
  358. static inline void pcmcia_socket_enable(pct, pch)
  359. pcmcia_chipset_tag_t pct;
  360. pcmcia_chipset_handle_t *pch;
  361. {
  362. pcmcia_chip_socket_enable(pct, pch);
  363. }
  364. static inline void pcmcia_socket_disable(pct, pch)
  365. pcmcia_chipset_tag_t pct;
  366. pcmcia_chipset_handle_t *pch;
  367. {
  368. pcmcia_chip_socket_disable(pct, pch);
  369. }
  370. /* Enable a PCMCIA function */
  371. int
  372. pcmcia_function_enable(pf)
  373. struct pcmcia_function *pf;
  374. {
  375. struct pcmcia_function *tmp;
  376. int reg;
  377. if (pf->cfe == NULL)
  378. panic("pcmcia_function_enable: function not initialized");
  379. /*
  380. * Increase the reference count on the socket, enabling power, if
  381. * necessary.
  382. */
  383. if (pf->sc->sc_enabled_count++ == 0)
  384. pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
  385. DPRINTF(("%s: ++enabled_count = %d\n", pf->sc->dev.dv_xname,
  386. pf->sc->sc_enabled_count));
  387. if (pf->pf_flags & PFF_ENABLED) {
  388. /*
  389. * Don't do anything if we're already enabled.
  390. */
  391. DPRINTF(("%s: pcmcia_function_enable on enabled func\n",
  392. pf->sc->dev.dv_xname));
  393. return (0);
  394. }
  395. /* If there was no CIS don't mess with CCR */
  396. if (pf->pf_flags & PFF_FAKE)
  397. goto done;
  398. /*
  399. * It's possible for different functions' CCRs to be in the same
  400. * underlying page. Check for that.
  401. */
  402. SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
  403. if ((tmp->pf_flags & PFF_ENABLED) &&
  404. (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
  405. ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
  406. (tmp->ccr_base - tmp->pf_ccr_offset +
  407. tmp->pf_ccr_realsize))) {
  408. pf->pf_ccrt = tmp->pf_ccrt;
  409. pf->pf_ccrh = tmp->pf_ccrh;
  410. pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
  411. /*
  412. * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
  413. * tmp->ccr_base) + pf->ccr_base;
  414. */
  415. pf->pf_ccr_offset =
  416. (tmp->pf_ccr_offset + pf->ccr_base) -
  417. tmp->ccr_base;
  418. pf->pf_ccr_window = tmp->pf_ccr_window;
  419. break;
  420. }
  421. }
  422. if (tmp == NULL) {
  423. if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
  424. goto bad;
  425. if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
  426. PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
  427. &pf->pf_ccr_window)) {
  428. pcmcia_mem_free(pf, &pf->pf_pcmh);
  429. goto bad;
  430. }
  431. }
  432. reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
  433. reg |= PCMCIA_CCR_OPTION_LEVIREQ;
  434. if (pcmcia_mfc(pf->sc)) {
  435. reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
  436. if (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))
  437. reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
  438. if (pf->ih_fct)
  439. reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
  440. }
  441. pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
  442. reg = 0;
  443. if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
  444. reg |= PCMCIA_CCR_STATUS_IOIS8;
  445. if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
  446. reg |= PCMCIA_CCR_STATUS_AUDIO;
  447. pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
  448. pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
  449. if (pcmcia_mfc(pf->sc)) {
  450. pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
  451. (pf->pf_mfc_iobase >> 0) & 0xff);
  452. pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
  453. (pf->pf_mfc_iobase >> 8) & 0xff);
  454. pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
  455. (pf->pf_mfc_iobase >> 16) & 0xff);
  456. pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
  457. (pf->pf_mfc_iobase >> 24) & 0xff);
  458. pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
  459. pf->pf_mfc_iomax - pf->pf_mfc_iobase);
  460. }
  461. #ifdef PCMCIADEBUG
  462. SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
  463. printf("%s: function %d CCR at %d offset %lx: "
  464. "%x %x %x %x, %x %x %x %x, %x\n",
  465. tmp->sc->dev.dv_xname, tmp->number,
  466. tmp->pf_ccr_window, tmp->pf_ccr_offset,
  467. pcmcia_ccr_read(tmp, 0x00),
  468. pcmcia_ccr_read(tmp, 0x02),
  469. pcmcia_ccr_read(tmp, 0x04),
  470. pcmcia_ccr_read(tmp, 0x06),
  471. pcmcia_ccr_read(tmp, 0x0A),
  472. pcmcia_ccr_read(tmp, 0x0C),
  473. pcmcia_ccr_read(tmp, 0x0E),
  474. pcmcia_ccr_read(tmp, 0x10),
  475. pcmcia_ccr_read(tmp, 0x12));
  476. }
  477. #endif
  478. done:
  479. pf->pf_flags |= PFF_ENABLED;
  480. delay(1000);
  481. return (0);
  482. bad:
  483. /*
  484. * Decrement the reference count, and power down the socket, if
  485. * necessary.
  486. */
  487. if (--pf->sc->sc_enabled_count == 0)
  488. pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
  489. DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
  490. pf->sc->sc_enabled_count));
  491. return (1);
  492. }
  493. /* Disable PCMCIA function. */
  494. void
  495. pcmcia_function_disable(pf)
  496. struct pcmcia_function *pf;
  497. {
  498. struct pcmcia_function *tmp;
  499. if (pf->cfe == NULL)
  500. panic("pcmcia_function_enable: function not initialized");
  501. if ((pf->pf_flags & PFF_ENABLED) == 0) {
  502. /*
  503. * Don't do anything if we're already disabled.
  504. */
  505. return;
  506. }
  507. /* If there was no CIS don't mess with CCR */
  508. if (pf->pf_flags & PFF_FAKE) {
  509. pf->pf_flags &= ~PFF_ENABLED;
  510. goto done;
  511. }
  512. /*
  513. * it's possible for different functions' CCRs to be in the same
  514. * underlying page. Check for that. Note we mark us as disabled
  515. * first to avoid matching ourself.
  516. */
  517. pf->pf_flags &= ~PFF_ENABLED;
  518. SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
  519. if ((tmp->pf_flags & PFF_ENABLED) &&
  520. (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
  521. ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
  522. (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
  523. break;
  524. }
  525. /* Not used by anyone else; unmap the CCR. */
  526. if (tmp == NULL) {
  527. pcmcia_mem_unmap(pf, pf->pf_ccr_window);
  528. pcmcia_mem_free(pf, &pf->pf_pcmh);
  529. }
  530. done:
  531. /*
  532. * Decrement the reference count, and power down the socket, if
  533. * necessary.
  534. */
  535. if (--pf->sc->sc_enabled_count == 0)
  536. pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
  537. DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
  538. pf->sc->sc_enabled_count));
  539. }
  540. int
  541. pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
  542. struct pcmcia_function *pf;
  543. int width;
  544. bus_addr_t offset;
  545. bus_size_t size;
  546. struct pcmcia_io_handle *pcihp;
  547. int *windowp;
  548. {
  549. int reg;
  550. if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
  551. width, offset, size, pcihp, windowp))
  552. return (1);
  553. /*
  554. * XXX In the multifunction multi-iospace-per-function case, this
  555. * needs to cooperate with io_alloc to make sure that the spaces
  556. * don't overlap, and that the ccr's are set correctly.
  557. */
  558. if (pcmcia_mfc(pf->sc) &&
  559. (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))) {
  560. bus_addr_t iobase = pcihp->addr;
  561. bus_addr_t iomax = pcihp->addr + pcihp->size - 1;
  562. if (pf->pf_mfc_iomax == 0) {
  563. pf->pf_mfc_iobase = iobase;
  564. pf->pf_mfc_iomax = iomax;
  565. } else {
  566. if (iobase < pf->pf_mfc_iobase)
  567. pf->pf_mfc_iobase = iobase;
  568. if (iomax > pf->pf_mfc_iomax)
  569. pf->pf_mfc_iomax = iomax;
  570. }
  571. pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
  572. (pf->pf_mfc_iobase >> 0) & 0xff);
  573. pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
  574. (pf->pf_mfc_iobase >> 8) & 0xff);
  575. pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
  576. (pf->pf_mfc_iobase >> 16) & 0xff);
  577. pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
  578. (pf->pf_mfc_iobase >> 24) & 0xff);
  579. pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
  580. pf->pf_mfc_iomax - pf->pf_mfc_iobase);
  581. reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
  582. reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
  583. pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
  584. }
  585. return (0);
  586. }
  587. void *
  588. pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg, xname)
  589. struct pcmcia_function *pf;
  590. int ipl;
  591. int (*ih_fct)(void *);
  592. void *ih_arg;
  593. char *xname;
  594. {
  595. void *ret;
  596. int s, ihcnt, hiipl, reg;
  597. struct pcmcia_function *pf2;
  598. /* Behave differently if this is a multifunction card. */
  599. if (pcmcia_mfc(pf->sc)) {
  600. /*
  601. * Mask all the ipl's which are already used by this card,
  602. * and find the highest ipl number (lowest priority).
  603. */
  604. ihcnt = 0;
  605. SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
  606. if (pf2->ih_fct) {
  607. DPRINTF(("%s: function %d has ih_fct %p\n",
  608. pf->sc->dev.dv_xname, pf2->number,
  609. pf2->ih_fct));
  610. if (ihcnt == 0)
  611. hiipl = pf2->ih_ipl;
  612. else if (pf2->ih_ipl > hiipl)
  613. hiipl = pf2->ih_ipl;
  614. ihcnt++;
  615. }
  616. }
  617. /*
  618. * Establish the real interrupt, changing the ipl if
  619. * necessary.
  620. */
  621. if (ihcnt == 0) {
  622. #ifdef DIAGNOSTIC
  623. if (pf->sc->ih != NULL)
  624. panic("card has intr handler, "
  625. "but no function does");
  626. #endif
  627. s = spltty();
  628. /* Set up the handler for the new function. */
  629. pf->ih_fct = ih_fct;
  630. pf->ih_arg = ih_arg;
  631. pf->ih_ipl = ipl;
  632. pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
  633. pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
  634. xname);
  635. splx(s);
  636. } else if (ipl > hiipl) {
  637. #ifdef DIAGNOSTIC
  638. if (pf->sc->ih == NULL)
  639. panic("functions have ih, "
  640. "but the card does not");
  641. #endif
  642. s = spltty();
  643. pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
  644. pf->sc->ih);
  645. /* set up the handler for the new function */
  646. pf->ih_fct = ih_fct;
  647. pf->ih_arg = ih_arg;
  648. pf->ih_ipl = ipl;
  649. pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
  650. pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
  651. xname);
  652. splx(s);
  653. } else {
  654. s = spltty();
  655. /* Set up the handler for the new function. */
  656. pf->ih_fct = ih_fct;
  657. pf->ih_arg = ih_arg;
  658. pf->ih_ipl = ipl;
  659. splx(s);
  660. }
  661. ret = pf->sc->ih;
  662. if (ret != NULL) {
  663. reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
  664. reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
  665. pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
  666. reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
  667. reg |= PCMCIA_CCR_STATUS_INTRACK;
  668. pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
  669. }
  670. } else
  671. ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
  672. pf, ipl, ih_fct, ih_arg, xname);
  673. return (ret);
  674. }
  675. void
  676. pcmcia_intr_disestablish(pf, ih)
  677. struct pcmcia_function *pf;
  678. void *ih;
  679. {
  680. int s, reg, ihcnt, hiipl;
  681. struct pcmcia_function *pf2;
  682. /* Behave differently if this is a multifunction card. */
  683. if (pcmcia_mfc(pf->sc)) {
  684. /*
  685. * Mask all the ipl's which are already used by this card,
  686. * and find the highest ipl number (lowest priority). Skip
  687. * the current function.
  688. */
  689. ihcnt = 0;
  690. SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
  691. if (pf2 == pf)
  692. continue;
  693. if (pf2->ih_fct) {
  694. if (ihcnt == 0)
  695. hiipl = pf2->ih_ipl;
  696. else if (pf2->ih_ipl > hiipl)
  697. hiipl = pf2->ih_ipl;
  698. ihcnt++;
  699. }
  700. }
  701. /*
  702. * If the ih being removed is lower priority than the lowest
  703. * priority remaining interrupt, up the priority.
  704. */
  705. /*
  706. * ihcnt is the number of interrupt handlers *not* including
  707. * the one about to be removed.
  708. */
  709. if (ihcnt == 0) {
  710. #ifdef DIAGNOSTIC
  711. if (pf->sc->ih == NULL)
  712. panic("disestablishing last function, but card has no ih");
  713. #endif
  714. pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
  715. pf->sc->ih);
  716. reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
  717. reg &= ~PCMCIA_CCR_OPTION_IREQ_ENABLE;
  718. pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
  719. pf->ih_fct = NULL;
  720. pf->ih_arg = NULL;
  721. pf->sc->ih = NULL;
  722. } else if (pf->ih_ipl > hiipl) {
  723. #ifdef DIAGNOSTIC
  724. if (pf->sc->ih == NULL)
  725. panic("changing ih ipl, but card has no ih");
  726. #endif
  727. s = spltty();
  728. pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
  729. pf->sc->ih);
  730. pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
  731. pf->sc->pch, pf, hiipl, pcmcia_card_intr, pf->sc,
  732. NULL);
  733. /* Null out the handler for this function. */
  734. pf->ih_fct = NULL;
  735. pf->ih_arg = NULL;
  736. splx(s);
  737. } else {
  738. s = spltty();
  739. pf->ih_fct = NULL;
  740. pf->ih_arg = NULL;
  741. splx(s);
  742. }
  743. } else
  744. pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
  745. }
  746. const char *
  747. pcmcia_intr_string(pf, ih)
  748. struct pcmcia_function *pf;
  749. void *ih;
  750. {
  751. return pcmcia_chip_intr_string(pf->sc->pct, pf->sc->pch, ih);
  752. }
  753. int
  754. pcmcia_card_intr(arg)
  755. void *arg;
  756. {
  757. struct pcmcia_softc *sc = arg;
  758. struct pcmcia_function *pf;
  759. int reg, ret, ret2;
  760. ret = 0;
  761. for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  762. pf = SIMPLEQ_NEXT(pf, pf_list)) {
  763. #ifdef PCMCIADEBUG
  764. printf("%s: intr flags=%x fct=%d cor=%02x csr=%02x pin=%02x",
  765. sc->dev.dv_xname, pf->pf_flags, pf->number,
  766. pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION),
  767. pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS),
  768. pcmcia_ccr_read(pf, PCMCIA_CCR_PIN));
  769. #endif
  770. if (pf->ih_fct != NULL &&
  771. (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) {
  772. reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
  773. if (reg & PCMCIA_CCR_STATUS_INTR) {
  774. ret2 = (*pf->ih_fct)(pf->ih_arg);
  775. if (ret2 != 0 && ret == 0)
  776. ret = ret2;
  777. reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
  778. #ifdef PCMCIADEBUG
  779. printf("; csr %02x->%02x",
  780. reg, reg & ~PCMCIA_CCR_STATUS_INTR);
  781. #endif
  782. pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
  783. reg & ~PCMCIA_CCR_STATUS_INTR);
  784. }
  785. }
  786. #ifdef PCMCIADEBUG
  787. printf("\n");
  788. #endif
  789. }
  790. return (ret);
  791. }