mkbc.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  1. /* $OpenBSD: mkbc.c,v 1.13 2015/02/11 07:05:39 dlg Exp $ */
  2. /*
  3. * Copyright (c) 2006, 2007, Joel Sing
  4. * 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 MIND,
  21. * USE, 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. * Derived from sys/dev/ic/pckbc.c under the following terms:
  28. * $NetBSD: pckbc.c,v 1.5 2000/06/09 04:58:35 soda Exp $ */
  29. /*
  30. * Copyright (c) 1998
  31. * Matthias Drochner. All rights reserved.
  32. *
  33. * Redistribution and use in source and binary forms, with or without
  34. * modification, are permitted provided that the following conditions
  35. * are met:
  36. * 1. Redistributions of source code must retain the above copyright
  37. * notice, this list of conditions and the following disclaimer.
  38. * 2. Redistributions in binary form must reproduce the above copyright
  39. * notice, this list of conditions and the following disclaimer in the
  40. * documentation and/or other materials provided with the distribution.
  41. *
  42. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  43. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  44. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  45. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  46. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  47. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  48. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  49. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  50. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  51. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  52. */
  53. /*
  54. * Driver for Moosehead PS/2 Controllers (mkbc)
  55. *
  56. * There are actually two separate controllers attached to the macebus.
  57. * However in the interest of reusing code, we want to act like a pckbc(4)
  58. * so that we can directly attach pckbd(4) and pms(4). As a result, we make
  59. * each controller look like a "slot" and combine them into a single device.
  60. *
  61. */
  62. #include <sys/param.h>
  63. #include <sys/systm.h>
  64. #include <sys/device.h>
  65. #include <sys/malloc.h>
  66. #include <sys/timeout.h>
  67. #include <sys/kernel.h>
  68. #include <sys/proc.h>
  69. #include <sys/signalvar.h>
  70. #include <sys/errno.h>
  71. #include <sys/queue.h>
  72. #include <machine/autoconf.h>
  73. #include <machine/bus.h>
  74. #include <mips64/archtype.h>
  75. #include <sgi/localbus/crimebus.h>
  76. #include <sgi/localbus/macebusvar.h>
  77. #include <dev/ic/pckbcvar.h>
  78. #include <dev/pckbc/pckbdvar.h>
  79. #include "mkbcreg.h"
  80. const char *mkbc_slot_names[] = { "kbd", "mouse" };
  81. #define KBC_DEVCMD_ACK 0xfa
  82. #define KBC_DEVCMD_RESEND 0xfe
  83. #define KBD_DELAY DELAY(8)
  84. struct mkbc_softc {
  85. struct pckbc_softc sc_pckbc;
  86. bus_space_tag_t iot;
  87. bus_space_handle_t ioh;
  88. };
  89. int mkbc_match(struct device *, void *, void *);
  90. void mkbc_attach(struct device *, struct device *, void *);
  91. struct cfattach mkbc_ca = {
  92. sizeof(struct mkbc_softc), mkbc_match, mkbc_attach
  93. };
  94. struct cfdriver mkbc_cd = {
  95. NULL, "mkbc", DV_DULL
  96. };
  97. /* Descriptor for one device command. */
  98. struct pckbc_devcmd {
  99. TAILQ_ENTRY(pckbc_devcmd) next;
  100. int flags;
  101. #define KBC_CMDFLAG_SYNC 1 /* Give descriptor back to caller. */
  102. #define KBC_CMDFLAG_SLOW 2
  103. u_char cmd[4];
  104. int cmdlen, cmdidx, retries;
  105. u_char response[4];
  106. int status, responselen, responseidx;
  107. };
  108. /* Data per slave device. */
  109. struct pckbc_slotdata {
  110. int polling; /* Don't read data port in interrupt handler. */
  111. TAILQ_HEAD(, pckbc_devcmd) cmdqueue; /* Active commands. */
  112. TAILQ_HEAD(, pckbc_devcmd) freequeue; /* Free commands. */
  113. #define NCMD 5
  114. struct pckbc_devcmd cmds[NCMD];
  115. bus_space_handle_t ioh;
  116. };
  117. #define CMD_IN_QUEUE(q) (TAILQ_FIRST(&(q)->cmdqueue) != NULL)
  118. static int mkbc_console;
  119. static struct pckbc_slotdata mkbc_cons_slotdata;
  120. struct pckbc_internal mkbc_consdata;
  121. void mkbc_start(struct pckbc_internal *, pckbc_slot_t);
  122. int mkbc_attach_slot(struct mkbc_softc *, pckbc_slot_t);
  123. void mkbc_init_slotdata(struct pckbc_slotdata *);
  124. int mkbc_submatch(struct device *, void *, void *);
  125. int mkbcprint(void *, const char *);
  126. int mkbcintr(void *);
  127. int mkbcintr_internal(struct pckbc_internal *, struct pckbc_softc *);
  128. void mkbc_cleanqueue(struct pckbc_slotdata *);
  129. void mkbc_cleanup(void *);
  130. void mkbc_poll(void *);
  131. int mkbc_cmdresponse(struct pckbc_internal *, pckbc_slot_t, u_char);
  132. int mkbc_poll_read(bus_space_tag_t, bus_space_handle_t);
  133. int mkbc_poll_write(bus_space_tag_t, bus_space_handle_t, int);
  134. int
  135. mkbc_match(struct device *parent, void *cf, void *aux)
  136. {
  137. return 1;
  138. }
  139. void
  140. mkbc_init_slotdata(struct pckbc_slotdata *q)
  141. {
  142. int i;
  143. TAILQ_INIT(&q->cmdqueue);
  144. TAILQ_INIT(&q->freequeue);
  145. for (i = 0; i < NCMD; i++) {
  146. TAILQ_INSERT_TAIL(&q->freequeue, &(q->cmds[i]), next);
  147. }
  148. q->polling = 0;
  149. }
  150. int
  151. mkbcprint(void *aux, const char *pnp)
  152. {
  153. struct pckbc_attach_args *pa = aux;
  154. if (!pnp)
  155. printf(" (%s slot)", mkbc_slot_names[pa->pa_slot]);
  156. return (QUIET);
  157. }
  158. int
  159. mkbc_submatch(struct device *parent, void *match, void *aux)
  160. {
  161. struct cfdata *cf = match;
  162. struct pckbc_attach_args *pa = aux;
  163. if (cf->cf_loc[PCKBCCF_SLOT] != PCKBCCF_SLOT_DEFAULT &&
  164. cf->cf_loc[PCKBCCF_SLOT] != pa->pa_slot)
  165. return (0);
  166. return ((*cf->cf_attach->ca_match)(parent, cf, aux));
  167. }
  168. int
  169. mkbc_attach_slot(struct mkbc_softc *msc, pckbc_slot_t slot)
  170. {
  171. struct pckbc_softc *sc = &msc->sc_pckbc;
  172. struct pckbc_internal *t = sc->id;
  173. struct pckbc_attach_args pa;
  174. bus_space_handle_t ioh;
  175. int found;
  176. if (!t->t_slotdata[slot]) {
  177. t->t_slotdata[slot] = malloc(sizeof(struct pckbc_slotdata),
  178. M_DEVBUF, M_NOWAIT);
  179. if (t->t_slotdata[slot] == NULL) {
  180. printf("Failed to allocate slot data!\n");
  181. return 0;
  182. }
  183. mkbc_init_slotdata(t->t_slotdata[slot]);
  184. /* Map subregion of bus space for this "slot". */
  185. if (bus_space_subregion(msc->iot, msc->ioh,
  186. MKBC_PORTSIZE * slot, MKBC_PORTSIZE, &ioh)) {
  187. printf("Unable to map slot subregion!\n");
  188. return 0;
  189. }
  190. t->t_slotdata[slot]->ioh = ioh;
  191. /* Initialise controller. */
  192. bus_space_write_8(msc->iot, ioh, MKBC_CONTROL,
  193. MKBC_CONTROL_TX_CLOCK_DISABLE | MKBC_CONTROL_RESET);
  194. delay(100); /* 100us */
  195. /* Enable controller. */
  196. bus_space_write_8(t->t_iot, t->t_slotdata[slot]->ioh,
  197. MKBC_CONTROL,
  198. MKBC_CONTROL_RX_CLOCK_ENABLE | MKBC_CONTROL_TX_ENABLE);
  199. }
  200. pa.pa_tag = t;
  201. pa.pa_slot = slot;
  202. found = (config_found_sm((struct device *)msc, &pa,
  203. mkbcprint, mkbc_submatch) != NULL);
  204. return (found);
  205. }
  206. void
  207. mkbc_attach(struct device *parent, struct device *self, void *aux)
  208. {
  209. struct mkbc_softc *msc = (void*)self;
  210. struct macebus_attach_args *maa = aux;
  211. struct pckbc_softc *sc = &msc->sc_pckbc;
  212. struct pckbc_internal *t;
  213. if (mkbc_console == 0) {
  214. /* Setup bus space mapping. */
  215. msc->iot = maa->maa_iot;
  216. if (bus_space_map(msc->iot, maa->maa_baseaddr,
  217. MKBC_PORTSIZE * 2, 0, &msc->ioh)) {
  218. printf(": unable to map bus space!\n");
  219. return;
  220. }
  221. /* Setup pckbc_internal structure. */
  222. t = malloc(sizeof(struct pckbc_internal), M_DEVBUF,
  223. M_WAITOK | M_ZERO);
  224. t->t_iot = msc->iot;
  225. t->t_ioh_d = 0;
  226. t->t_ioh_c = 0;
  227. t->t_addr = maa->maa_baseaddr;
  228. t->t_sc = (struct pckbc_softc *)msc;
  229. sc->id = t;
  230. timeout_set(&t->t_cleanup, mkbc_cleanup, t);
  231. timeout_set(&t->t_poll, mkbc_poll, t);
  232. } else {
  233. /* Things have already been setup in mkbc_cnattach. */
  234. msc->iot = mkbc_consdata.t_iot;
  235. msc->ioh = mkbc_consdata.t_ioh_d;
  236. mkbc_consdata.t_sc = (struct pckbc_softc *)msc;
  237. sc->id = &mkbc_consdata;
  238. }
  239. /* Establish interrupt handler. */
  240. if (macebus_intr_establish(maa->maa_intr, maa->maa_mace_intr,
  241. IST_EDGE, IPL_TTY, mkbcintr, msc, sc->sc_dv.dv_xname))
  242. printf("\n");
  243. else
  244. printf(": unable to establish interrupt\n");
  245. /*
  246. * Attach "slots" - technically these are separate controllers
  247. * in the same bus space, however we want to act like pckbc(4) so
  248. * that we can attach pckbd(4) and pms(4).
  249. */
  250. mkbc_attach_slot(msc, PCKBC_KBD_SLOT);
  251. mkbc_attach_slot(msc, PCKBC_AUX_SLOT);
  252. }
  253. int
  254. mkbcintr(void *vsc)
  255. {
  256. struct mkbc_softc *msc = (struct mkbc_softc *)vsc;
  257. struct pckbc_softc *sc = &msc->sc_pckbc;
  258. struct pckbc_internal *t = sc->id;
  259. return mkbcintr_internal(t, sc);
  260. }
  261. int
  262. mkbcintr_internal(struct pckbc_internal *t, struct pckbc_softc *sc)
  263. {
  264. pckbc_slot_t slot;
  265. struct pckbc_slotdata *q;
  266. int served = 0;
  267. u_int64_t stat;
  268. u_int64_t data;
  269. /* Reschedule timeout further into the idle times. */
  270. if (timeout_pending(&t->t_poll))
  271. timeout_add_sec(&t->t_poll, 1);
  272. /*
  273. * Need to check both "slots" since interrupt could be from
  274. * either controller.
  275. */
  276. slot = PCKBC_KBD_SLOT;
  277. q = t->t_slotdata[slot];
  278. for(;;) {
  279. if (!q) {
  280. printf("mkbcintr: no kbd slot data!\n");
  281. break;
  282. }
  283. stat = bus_space_read_8(t->t_iot, q->ioh, MKBC_STATUS);
  284. if (!(stat & MKBC_STATUS_RX_FULL))
  285. break;
  286. served = 1;
  287. if (q->polling)
  288. break; /* pckbc_poll_data() will get it */
  289. KBD_DELAY;
  290. data = bus_space_read_8(t->t_iot, q->ioh, MKBC_RX_PORT) & 0xff;
  291. if (CMD_IN_QUEUE(q) && mkbc_cmdresponse(t, slot, data))
  292. continue;
  293. if (sc->inputhandler[slot])
  294. (*sc->inputhandler[slot])(sc->inputarg[slot], data);
  295. #ifdef MKBCDEBUG
  296. else
  297. printf("mkbcintr: slot %d lost %d\n", slot, data);
  298. #endif
  299. }
  300. /* Mouse controller/slot. */
  301. slot = PCKBC_AUX_SLOT;
  302. q = t->t_slotdata[slot];
  303. for(;;) {
  304. if (!q) {
  305. printf("mkbcintr: no mouse slot data!\n");
  306. break;
  307. }
  308. stat = bus_space_read_8(t->t_iot, q->ioh, MKBC_STATUS);
  309. if (!(stat & MKBC_STATUS_RX_FULL))
  310. break;
  311. served = 1;
  312. if (q->polling)
  313. break; /* pckbc_poll_data() will get it. */
  314. KBD_DELAY;
  315. data = bus_space_read_8(t->t_iot, q->ioh, MKBC_RX_PORT) & 0xff;
  316. if (CMD_IN_QUEUE(q) && mkbc_cmdresponse(t, slot, data))
  317. continue;
  318. if (sc->inputhandler[slot])
  319. (*sc->inputhandler[slot])(sc->inputarg[slot], data);
  320. #ifdef MKBCDEBUG
  321. else
  322. printf("mkbcintr: slot %d lost %d\n", slot, data);
  323. #endif
  324. }
  325. return (served);
  326. }
  327. int
  328. mkbc_poll_write(bus_space_tag_t iot, bus_space_handle_t ioh, int val)
  329. {
  330. int timeout = 10000;
  331. u_int64_t stat;
  332. /* Attempt to write a value to the controller. */
  333. while (timeout--) {
  334. stat = bus_space_read_8(iot, ioh, MKBC_STATUS);
  335. if (stat & MKBC_STATUS_TX_EMPTY) {
  336. bus_space_write_8(iot, ioh, MKBC_TX_PORT, val & 0xff);
  337. return 0;
  338. }
  339. delay(50);
  340. }
  341. return -1;
  342. }
  343. int
  344. mkbc_poll_read(bus_space_tag_t iot, bus_space_handle_t ioh)
  345. {
  346. int timeout = 10000;
  347. u_int64_t stat, val;
  348. /* Poll input from controller. */
  349. while (timeout--) {
  350. stat = bus_space_read_8(iot, ioh, MKBC_STATUS);
  351. if (stat & MKBC_STATUS_RX_FULL) {
  352. val = bus_space_read_8(iot, ioh, MKBC_RX_PORT);
  353. return val & 0xff;
  354. }
  355. delay(50);
  356. }
  357. return -1;
  358. }
  359. /*
  360. * Pass command to device, poll for ACK and data.
  361. * to be called at spltty()
  362. */
  363. static void
  364. mkbc_poll_cmd(struct pckbc_internal *t, pckbc_slot_t slot,
  365. struct pckbc_devcmd *cmd)
  366. {
  367. bus_space_tag_t iot = t->t_iot;
  368. bus_space_handle_t ioh = t->t_slotdata[slot]->ioh;
  369. int i, c = 0;
  370. while (cmd->cmdidx < cmd->cmdlen) {
  371. if (mkbc_poll_write(iot, ioh, cmd->cmd[cmd->cmdidx]) == -1) {
  372. printf("mkbc_poll_cmd: send error\n");
  373. cmd->status = EIO;
  374. return;
  375. }
  376. for (i = 10; i; i--) { /* 1s ??? */
  377. c = mkbc_poll_read(iot, ioh);
  378. if (c != -1)
  379. break;
  380. }
  381. if (c == KBC_DEVCMD_ACK) {
  382. cmd->cmdidx++;
  383. continue;
  384. }
  385. if (c == KBC_DEVCMD_RESEND) {
  386. #ifdef MKBCDEBUG
  387. printf("mkbc_cmd: RESEND\n");
  388. #endif
  389. if (cmd->retries++ < 5)
  390. continue;
  391. else {
  392. #ifdef MKBCDEBUG
  393. printf("mkbc: cmd failed\n");
  394. #endif
  395. cmd->status = EIO;
  396. return;
  397. }
  398. }
  399. if (c == -1) {
  400. #ifdef MKBCDEBUG
  401. printf("mkbc_cmd: timeout\n");
  402. #endif
  403. cmd->status = EIO;
  404. return;
  405. }
  406. #ifdef MKBCDEBUG
  407. printf("mkbc_cmd: lost 0x%x\n", c);
  408. #endif
  409. }
  410. while (cmd->responseidx < cmd->responselen) {
  411. if (cmd->flags & KBC_CMDFLAG_SLOW)
  412. i = 100; /* 10s ??? */
  413. else
  414. i = 10; /* 1s ??? */
  415. while (i--) {
  416. c = mkbc_poll_read(iot, ioh);
  417. if (c != -1)
  418. break;
  419. }
  420. if (c == -1) {
  421. #ifdef MKBCDEBUG
  422. printf("mkbc_poll_cmd: no data\n");
  423. #endif
  424. cmd->status = ETIMEDOUT;
  425. return;
  426. } else
  427. cmd->response[cmd->responseidx++] = c;
  428. }
  429. }
  430. /*
  431. * Clean up a command queue, throw away everything.
  432. */
  433. void
  434. mkbc_cleanqueue(struct pckbc_slotdata *q)
  435. {
  436. struct pckbc_devcmd *cmd;
  437. #ifdef MKBCDEBUG
  438. int i;
  439. #endif
  440. while ((cmd = TAILQ_FIRST(&q->cmdqueue))) {
  441. TAILQ_REMOVE(&q->cmdqueue, cmd, next);
  442. #ifdef MKBCDEBUG
  443. printf("mkbc_cleanqueue: removing");
  444. for (i = 0; i < cmd->cmdlen; i++)
  445. printf(" %02x", cmd->cmd[i]);
  446. printf("\n");
  447. #endif
  448. TAILQ_INSERT_TAIL(&q->freequeue, cmd, next);
  449. }
  450. }
  451. /*
  452. * Timeout error handler: clean queues and data port.
  453. * XXX could be less invasive.
  454. */
  455. void
  456. mkbc_cleanup(void *self)
  457. {
  458. struct pckbc_internal *t = self;
  459. int s;
  460. printf("mkbc: command timeout\n");
  461. s = spltty();
  462. if (t->t_slotdata[PCKBC_KBD_SLOT])
  463. mkbc_cleanqueue(t->t_slotdata[PCKBC_KBD_SLOT]);
  464. if (t->t_slotdata[PCKBC_AUX_SLOT])
  465. mkbc_cleanqueue(t->t_slotdata[PCKBC_AUX_SLOT]);
  466. while (mkbc_poll_read(t->t_iot, t->t_slotdata[PCKBC_KBD_SLOT]->ioh)
  467. != -1) ;
  468. while (mkbc_poll_read(t->t_iot, t->t_slotdata[PCKBC_AUX_SLOT]->ioh)
  469. != -1) ;
  470. /* Reset KBC? */
  471. splx(s);
  472. }
  473. /*
  474. * Pass command to device during normal operation.
  475. * to be called at spltty()
  476. */
  477. void
  478. mkbc_start(struct pckbc_internal *t, pckbc_slot_t slot)
  479. {
  480. struct pckbc_slotdata *q = t->t_slotdata[slot];
  481. struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue);
  482. if (q->polling) {
  483. do {
  484. mkbc_poll_cmd(t, slot, cmd);
  485. if (cmd->status)
  486. printf("mkbc_start: command error\n");
  487. TAILQ_REMOVE(&q->cmdqueue, cmd, next);
  488. if (cmd->flags & KBC_CMDFLAG_SYNC)
  489. wakeup(cmd);
  490. else {
  491. timeout_del(&t->t_cleanup);
  492. TAILQ_INSERT_TAIL(&q->freequeue, cmd, next);
  493. }
  494. cmd = TAILQ_FIRST(&q->cmdqueue);
  495. } while (cmd);
  496. return;
  497. }
  498. if (mkbc_poll_write(t->t_iot, t->t_slotdata[slot]->ioh,
  499. cmd->cmd[cmd->cmdidx])) {
  500. printf("mkbc_start: send error\n");
  501. /* XXX what now? */
  502. return;
  503. }
  504. }
  505. /*
  506. * Handle command responses coming in asynchronously,
  507. * return nonzero if valid response.
  508. * to be called at spltty()
  509. */
  510. int
  511. mkbc_cmdresponse(struct pckbc_internal *t, pckbc_slot_t slot, u_char data)
  512. {
  513. struct pckbc_slotdata *q = t->t_slotdata[slot];
  514. struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue);
  515. #ifdef DIAGNOSTIC
  516. if (!cmd)
  517. panic("mkbc_cmdresponse: no active command");
  518. #endif
  519. if (cmd->cmdidx < cmd->cmdlen) {
  520. if (data != KBC_DEVCMD_ACK && data != KBC_DEVCMD_RESEND)
  521. return (0);
  522. if (data == KBC_DEVCMD_RESEND) {
  523. if (cmd->retries++ < 5) {
  524. /* try again last command */
  525. goto restart;
  526. } else {
  527. #ifdef MKBCDEBUG
  528. printf("mkbc: cmd failed\n");
  529. #endif
  530. cmd->status = EIO;
  531. /* dequeue */
  532. }
  533. } else {
  534. if (++cmd->cmdidx < cmd->cmdlen)
  535. goto restart;
  536. if (cmd->responselen)
  537. return (1);
  538. /* else dequeue */
  539. }
  540. } else if (cmd->responseidx < cmd->responselen) {
  541. cmd->response[cmd->responseidx++] = data;
  542. if (cmd->responseidx < cmd->responselen)
  543. return (1);
  544. /* else dequeue */
  545. } else
  546. return (0);
  547. /* dequeue: */
  548. TAILQ_REMOVE(&q->cmdqueue, cmd, next);
  549. if (cmd->flags & KBC_CMDFLAG_SYNC)
  550. wakeup(cmd);
  551. else {
  552. timeout_del(&t->t_cleanup);
  553. TAILQ_INSERT_TAIL(&q->freequeue, cmd, next);
  554. }
  555. if (!CMD_IN_QUEUE(q))
  556. return (1);
  557. restart:
  558. mkbc_start(t, slot);
  559. return (1);
  560. }
  561. /*
  562. * Interfaces to act like pckbc(4).
  563. */
  564. int
  565. pckbc_xt_translation(pckbc_tag_t self)
  566. {
  567. /* Translation isn't supported... */
  568. return (-1);
  569. }
  570. /* For use in autoconfiguration. */
  571. int
  572. pckbc_poll_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len,
  573. int responselen, u_char *respbuf, int slow)
  574. {
  575. struct pckbc_devcmd nc;
  576. int s;
  577. if ((len > 4) || (responselen > 4))
  578. return (EINVAL);
  579. bzero(&nc, sizeof(nc));
  580. bcopy(cmd, nc.cmd, len);
  581. nc.cmdlen = len;
  582. nc.responselen = responselen;
  583. nc.flags = (slow ? KBC_CMDFLAG_SLOW : 0);
  584. s = spltty();
  585. mkbc_poll_cmd(self, slot, &nc);
  586. splx(s);
  587. if (nc.status == 0 && respbuf)
  588. bcopy(nc.response, respbuf, responselen);
  589. return (nc.status);
  590. }
  591. void
  592. pckbc_flush(pckbc_tag_t self, pckbc_slot_t slot)
  593. {
  594. /* Read any data and discard. */
  595. struct pckbc_internal *t = self;
  596. (void) mkbc_poll_read(t->t_iot, t->t_slotdata[slot]->ioh);
  597. }
  598. /*
  599. * Put command into the device's command queue, return zero or errno.
  600. */
  601. int
  602. pckbc_enqueue_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len,
  603. int responselen, int sync, u_char *respbuf)
  604. {
  605. struct pckbc_internal *t = self;
  606. struct pckbc_slotdata *q = t->t_slotdata[slot];
  607. struct pckbc_devcmd *nc;
  608. int s, isactive, res = 0;
  609. if ((len > 4) || (responselen > 4))
  610. return (EINVAL);
  611. s = spltty();
  612. nc = TAILQ_FIRST(&q->freequeue);
  613. if (nc) {
  614. TAILQ_REMOVE(&q->freequeue, nc, next);
  615. }
  616. splx(s);
  617. if (!nc)
  618. return (ENOMEM);
  619. bzero(nc, sizeof(*nc));
  620. bcopy(cmd, nc->cmd, len);
  621. nc->cmdlen = len;
  622. nc->responselen = responselen;
  623. nc->flags = (sync ? KBC_CMDFLAG_SYNC : 0);
  624. s = spltty();
  625. if (q->polling && sync) {
  626. /*
  627. * XXX We should poll until the queue is empty.
  628. * But we don't come here normally, so make
  629. * it simple and throw away everything.
  630. */
  631. mkbc_cleanqueue(q);
  632. }
  633. isactive = CMD_IN_QUEUE(q);
  634. TAILQ_INSERT_TAIL(&q->cmdqueue, nc, next);
  635. if (!isactive)
  636. mkbc_start(t, slot);
  637. if (q->polling)
  638. res = (sync ? nc->status : 0);
  639. else if (sync) {
  640. if ((res = tsleep(nc, 0, "kbccmd", 1*hz))) {
  641. TAILQ_REMOVE(&q->cmdqueue, nc, next);
  642. mkbc_cleanup(t);
  643. } else
  644. res = nc->status;
  645. } else
  646. timeout_add_sec(&t->t_cleanup, 1);
  647. if (sync) {
  648. if (respbuf)
  649. bcopy(nc->response, respbuf, responselen);
  650. TAILQ_INSERT_TAIL(&q->freequeue, nc, next);
  651. }
  652. splx(s);
  653. return (res);
  654. }
  655. int
  656. pckbc_poll_data(pckbc_tag_t self, pckbc_slot_t slot)
  657. {
  658. struct pckbc_internal *t = self;
  659. struct pckbc_slotdata *q = t->t_slotdata[slot];
  660. int c;
  661. c = mkbc_poll_read(t->t_iot, q->ioh);
  662. if (c != -1 && q && CMD_IN_QUEUE(q)) {
  663. /* We jumped into a running command - try to deliver the
  664. response. */
  665. if (mkbc_cmdresponse(t, slot, c))
  666. return (-1);
  667. }
  668. return (c);
  669. }
  670. void
  671. pckbc_set_inputhandler(pckbc_tag_t self, pckbc_slot_t slot, pckbc_inputfcn func,
  672. void *arg, char *name)
  673. {
  674. struct pckbc_internal *t = (struct pckbc_internal *)self;
  675. struct pckbc_softc *sc = t->t_sc;
  676. if (slot >= PCKBC_NSLOTS)
  677. panic("mkbc_set_inputhandler: bad slot %d", slot);
  678. sc->inputhandler[slot] = func;
  679. sc->inputarg[slot] = arg;
  680. sc->subname[slot] = name;
  681. if (mkbc_console && slot == PCKBC_KBD_SLOT)
  682. timeout_add_sec(&t->t_poll, 1);
  683. }
  684. void
  685. pckbc_slot_enable(pckbc_tag_t self, pckbc_slot_t slot, int on)
  686. {
  687. struct pckbc_internal *t = (struct pckbc_internal *)self;
  688. /*
  689. * Should we also enable/disable the controller??
  690. * If we did then none of the poll_ functions would work...
  691. */
  692. if (on) {
  693. /* Enable controller interrupts. */
  694. bus_space_write_8(t->t_iot, t->t_slotdata[slot]->ioh,
  695. MKBC_CONTROL,
  696. MKBC_CONTROL_RX_CLOCK_ENABLE | MKBC_CONTROL_TX_ENABLE
  697. | MKBC_CONTROL_RX_INT_ENABLE);
  698. } else {
  699. /* Disable controller interrupts. */
  700. bus_space_write_8(t->t_iot, t->t_slotdata[slot]->ioh,
  701. MKBC_CONTROL,
  702. MKBC_CONTROL_RX_CLOCK_ENABLE | MKBC_CONTROL_TX_ENABLE);
  703. }
  704. if (slot == PCKBC_KBD_SLOT) {
  705. if (on)
  706. timeout_add_sec(&t->t_poll, 1);
  707. else
  708. timeout_del(&t->t_poll);
  709. }
  710. }
  711. void
  712. pckbc_set_poll(pckbc_tag_t self, pckbc_slot_t slot, int on)
  713. {
  714. struct pckbc_internal *t = (struct pckbc_internal *)self;
  715. t->t_slotdata[slot]->polling = on;
  716. if (!on) {
  717. int s;
  718. /*
  719. * If disabling polling on a device that's been configured,
  720. * make sure there are no bytes left in the FIFO, holding up
  721. * the interrupt line. Otherwise we won't get any further
  722. * interrupts.
  723. */
  724. if (t->t_sc) {
  725. s = spltty();
  726. mkbcintr(t->t_sc);
  727. splx(s);
  728. }
  729. }
  730. }
  731. int
  732. mkbc_cnattach(bus_space_tag_t iot, bus_addr_t addr)
  733. {
  734. bus_space_handle_t ioh, slot_ioh;
  735. int res = 0;
  736. /* Ensure that we're on an O2. */
  737. if (sys_config.system_type != SGI_O2)
  738. return (ENXIO);
  739. if (bus_space_map(iot, addr, MKBC_PORTSIZE * 2, 0, &ioh))
  740. return (ENXIO);
  741. mkbc_consdata.t_addr = addr;
  742. mkbc_consdata.t_iot = iot;
  743. mkbc_consdata.t_ioh_d = ioh;
  744. /* Map subregion of bus space for this "slot". */
  745. if (bus_space_subregion(iot, ioh, 0, MKBC_PORTSIZE, &slot_ioh)) {
  746. bus_space_unmap(iot, ioh, MKBC_PORTSIZE * 2);
  747. return (ENXIO);
  748. }
  749. mkbc_cons_slotdata.ioh = slot_ioh;
  750. mkbc_init_slotdata(&mkbc_cons_slotdata);
  751. mkbc_consdata.t_slotdata[PCKBC_KBD_SLOT] = &mkbc_cons_slotdata;
  752. /* Initialise controller. */
  753. bus_space_write_8(iot, slot_ioh, MKBC_CONTROL,
  754. MKBC_CONTROL_TX_CLOCK_DISABLE | MKBC_CONTROL_RESET);
  755. delay(100); /* 100us */
  756. /* Enable controller. */
  757. bus_space_write_8(iot, slot_ioh, MKBC_CONTROL,
  758. MKBC_CONTROL_RX_CLOCK_ENABLE | MKBC_CONTROL_TX_ENABLE
  759. | MKBC_CONTROL_RX_INT_ENABLE);
  760. timeout_set(&mkbc_consdata.t_cleanup, mkbc_cleanup, &mkbc_consdata);
  761. timeout_set(&mkbc_consdata.t_poll, mkbc_poll, &mkbc_consdata);
  762. /* Flush input buffer. */
  763. (void) mkbc_poll_read(iot, slot_ioh);
  764. res = pckbd_cnattach(&mkbc_consdata);
  765. if (res) {
  766. bus_space_unmap(iot, ioh, MKBC_PORTSIZE * 2);
  767. } else {
  768. mkbc_console = 1;
  769. }
  770. return (res);
  771. }
  772. void
  773. mkbc_poll(void *self)
  774. {
  775. struct pckbc_internal *t = self;
  776. int s;
  777. s = spltty();
  778. (void)mkbcintr_internal(t, t->t_sc);
  779. timeout_add_sec(&t->t_poll, 1);
  780. splx(s);
  781. }