viocons.c 30 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162
  1. /* -*- linux-c -*-
  2. *
  3. * drivers/char/viocons.c
  4. *
  5. * iSeries Virtual Terminal
  6. *
  7. * Authors: Dave Boutcher <boutcher@us.ibm.com>
  8. * Ryan Arnold <ryanarn@us.ibm.com>
  9. * Colin Devilbiss <devilbis@us.ibm.com>
  10. * Stephen Rothwell <sfr@au1.ibm.com>
  11. *
  12. * (C) Copyright 2000, 2001, 2002, 2003, 2004 IBM Corporation
  13. *
  14. * This program is free software; you can redistribute it and/or
  15. * modify it under the terms of the GNU General Public License as
  16. * published by the Free Software Foundation; either version 2 of the
  17. * License, or (at your option) anyu later version.
  18. *
  19. * This program is distributed in the hope that it will be useful, but
  20. * WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  22. * General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, write to the Free Software Foundation,
  26. * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  27. */
  28. #include <linux/kernel.h>
  29. #include <linux/proc_fs.h>
  30. #include <linux/errno.h>
  31. #include <linux/vmalloc.h>
  32. #include <linux/mm.h>
  33. #include <linux/console.h>
  34. #include <linux/module.h>
  35. #include <asm/uaccess.h>
  36. #include <linux/init.h>
  37. #include <linux/wait.h>
  38. #include <linux/spinlock.h>
  39. #include <asm/ioctls.h>
  40. #include <linux/kd.h>
  41. #include <linux/tty.h>
  42. #include <linux/tty_flip.h>
  43. #include <linux/sysrq.h>
  44. #include <asm/iseries/vio.h>
  45. #include <asm/iseries/hv_lp_event.h>
  46. #include <asm/iseries/hv_call_event.h>
  47. #include <asm/iseries/hv_lp_config.h>
  48. #include <asm/iseries/hv_call.h>
  49. #ifdef CONFIG_VT
  50. #error You must turn off CONFIG_VT to use CONFIG_VIOCONS
  51. #endif
  52. #define VIOTTY_MAGIC (0x0DCB)
  53. #define VTTY_PORTS 10
  54. #define VIOCONS_KERN_WARN KERN_WARNING "viocons: "
  55. #define VIOCONS_KERN_INFO KERN_INFO "viocons: "
  56. static DEFINE_SPINLOCK(consolelock);
  57. static DEFINE_SPINLOCK(consoleloglock);
  58. #ifdef CONFIG_MAGIC_SYSRQ
  59. static int vio_sysrq_pressed;
  60. extern int sysrq_enabled;
  61. #endif
  62. #define VIOCHAR_NUM_BUF 16
  63. /*
  64. * Our port information. We store a pointer to one entry in the
  65. * tty_driver_data
  66. */
  67. static struct port_info {
  68. int magic;
  69. struct tty_struct *tty;
  70. HvLpIndex lp;
  71. u8 vcons;
  72. u64 seq; /* sequence number of last HV send */
  73. u64 ack; /* last ack from HV */
  74. /*
  75. * When we get writes faster than we can send it to the partition,
  76. * buffer the data here. Note that used is a bit map of used buffers.
  77. * It had better have enough bits to hold VIOCHAR_NUM_BUF the bitops assume
  78. * it is a multiple of unsigned long
  79. */
  80. unsigned long used;
  81. u8 *buffer[VIOCHAR_NUM_BUF];
  82. int bufferBytes[VIOCHAR_NUM_BUF];
  83. int curbuf;
  84. int bufferOverflow;
  85. int overflowMessage;
  86. } port_info[VTTY_PORTS];
  87. #define viochar_is_console(pi) ((pi) == &port_info[0])
  88. #define viochar_port(pi) ((pi) - &port_info[0])
  89. static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp);
  90. static struct tty_driver *viotty_driver;
  91. static void hvlog(char *fmt, ...)
  92. {
  93. int i;
  94. unsigned long flags;
  95. va_list args;
  96. static char buf[256];
  97. spin_lock_irqsave(&consoleloglock, flags);
  98. va_start(args, fmt);
  99. i = vscnprintf(buf, sizeof(buf) - 1, fmt, args);
  100. va_end(args);
  101. buf[i++] = '\r';
  102. HvCall_writeLogBuffer(buf, i);
  103. spin_unlock_irqrestore(&consoleloglock, flags);
  104. }
  105. static void hvlogOutput(const char *buf, int count)
  106. {
  107. unsigned long flags;
  108. int begin;
  109. int index;
  110. static const char cr = '\r';
  111. begin = 0;
  112. spin_lock_irqsave(&consoleloglock, flags);
  113. for (index = 0; index < count; index++) {
  114. if (buf[index] == '\n') {
  115. /*
  116. * Start right after the last '\n' or at the zeroth
  117. * array position and output the number of characters
  118. * including the newline.
  119. */
  120. HvCall_writeLogBuffer(&buf[begin], index - begin + 1);
  121. begin = index + 1;
  122. HvCall_writeLogBuffer(&cr, 1);
  123. }
  124. }
  125. if ((index - begin) > 0)
  126. HvCall_writeLogBuffer(&buf[begin], index - begin);
  127. spin_unlock_irqrestore(&consoleloglock, flags);
  128. }
  129. /*
  130. * Make sure we're pointing to a valid port_info structure. Shamelessly
  131. * plagerized from serial.c
  132. */
  133. static inline int viotty_paranoia_check(struct port_info *pi,
  134. char *name, const char *routine)
  135. {
  136. static const char *bad_pi_addr = VIOCONS_KERN_WARN
  137. "warning: bad address for port_info struct (%s) in %s\n";
  138. static const char *badmagic = VIOCONS_KERN_WARN
  139. "warning: bad magic number for port_info struct (%s) in %s\n";
  140. if ((pi < &port_info[0]) || (viochar_port(pi) > VTTY_PORTS)) {
  141. printk(bad_pi_addr, name, routine);
  142. return 1;
  143. }
  144. if (pi->magic != VIOTTY_MAGIC) {
  145. printk(badmagic, name, routine);
  146. return 1;
  147. }
  148. return 0;
  149. }
  150. /*
  151. * Add data to our pending-send buffers.
  152. *
  153. * NOTE: Don't use printk in here because it gets nastily recursive.
  154. * hvlog can be used to log to the hypervisor buffer
  155. */
  156. static int buffer_add(struct port_info *pi, const char *buf, size_t len)
  157. {
  158. size_t bleft;
  159. size_t curlen;
  160. const char *curbuf;
  161. int nextbuf;
  162. curbuf = buf;
  163. bleft = len;
  164. while (bleft > 0) {
  165. /*
  166. * If there is no space left in the current buffer, we have
  167. * filled everything up, so return. If we filled the previous
  168. * buffer we would already have moved to the next one.
  169. */
  170. if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) {
  171. hvlog ("\n\rviocons: No overflow buffer available for memcpy().\n");
  172. pi->bufferOverflow++;
  173. pi->overflowMessage = 1;
  174. break;
  175. }
  176. /*
  177. * Turn on the "used" bit for this buffer. If it's already on,
  178. * that's fine.
  179. */
  180. set_bit(pi->curbuf, &pi->used);
  181. /*
  182. * See if this buffer has been allocated. If not, allocate it.
  183. */
  184. if (pi->buffer[pi->curbuf] == NULL) {
  185. pi->buffer[pi->curbuf] =
  186. kmalloc(VIOCHAR_MAX_DATA, GFP_ATOMIC);
  187. if (pi->buffer[pi->curbuf] == NULL) {
  188. hvlog("\n\rviocons: kmalloc failed allocating spaces for buffer %d.",
  189. pi->curbuf);
  190. break;
  191. }
  192. }
  193. /* Figure out how much we can copy into this buffer. */
  194. if (bleft < (VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf]))
  195. curlen = bleft;
  196. else
  197. curlen = VIOCHAR_MAX_DATA - pi->bufferBytes[pi->curbuf];
  198. /* Copy the data into the buffer. */
  199. memcpy(pi->buffer[pi->curbuf] + pi->bufferBytes[pi->curbuf],
  200. curbuf, curlen);
  201. pi->bufferBytes[pi->curbuf] += curlen;
  202. curbuf += curlen;
  203. bleft -= curlen;
  204. /*
  205. * Now see if we've filled this buffer. If not then
  206. * we'll try to use it again later. If we've filled it
  207. * up then we'll advance the curbuf to the next in the
  208. * circular queue.
  209. */
  210. if (pi->bufferBytes[pi->curbuf] == VIOCHAR_MAX_DATA) {
  211. nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF;
  212. /*
  213. * Move to the next buffer if it hasn't been used yet
  214. */
  215. if (test_bit(nextbuf, &pi->used) == 0)
  216. pi->curbuf = nextbuf;
  217. }
  218. }
  219. return len - bleft;
  220. }
  221. /*
  222. * Send pending data
  223. *
  224. * NOTE: Don't use printk in here because it gets nastily recursive.
  225. * hvlog can be used to log to the hypervisor buffer
  226. */
  227. static void send_buffers(struct port_info *pi)
  228. {
  229. HvLpEvent_Rc hvrc;
  230. int nextbuf;
  231. struct viocharlpevent *viochar;
  232. unsigned long flags;
  233. spin_lock_irqsave(&consolelock, flags);
  234. viochar = (struct viocharlpevent *)
  235. vio_get_event_buffer(viomajorsubtype_chario);
  236. /* Make sure we got a buffer */
  237. if (viochar == NULL) {
  238. hvlog("\n\rviocons: Can't get viochar buffer in sendBuffers().");
  239. spin_unlock_irqrestore(&consolelock, flags);
  240. return;
  241. }
  242. if (pi->used == 0) {
  243. hvlog("\n\rviocons: in sendbuffers(), but no buffers used.\n");
  244. vio_free_event_buffer(viomajorsubtype_chario, viochar);
  245. spin_unlock_irqrestore(&consolelock, flags);
  246. return;
  247. }
  248. /*
  249. * curbuf points to the buffer we're filling. We want to
  250. * start sending AFTER this one.
  251. */
  252. nextbuf = (pi->curbuf + 1) % VIOCHAR_NUM_BUF;
  253. /*
  254. * Loop until we find a buffer with the used bit on
  255. */
  256. while (test_bit(nextbuf, &pi->used) == 0)
  257. nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF;
  258. initDataEvent(viochar, pi->lp);
  259. /*
  260. * While we have buffers with data, and our send window
  261. * is open, send them
  262. */
  263. while ((test_bit(nextbuf, &pi->used)) &&
  264. ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) {
  265. viochar->len = pi->bufferBytes[nextbuf];
  266. viochar->event.xCorrelationToken = pi->seq++;
  267. viochar->event.xSizeMinus1 =
  268. offsetof(struct viocharlpevent, data) + viochar->len;
  269. memcpy(viochar->data, pi->buffer[nextbuf], viochar->len);
  270. hvrc = HvCallEvent_signalLpEvent(&viochar->event);
  271. if (hvrc) {
  272. /*
  273. * MUST unlock the spinlock before doing a printk
  274. */
  275. vio_free_event_buffer(viomajorsubtype_chario, viochar);
  276. spin_unlock_irqrestore(&consolelock, flags);
  277. printk(VIOCONS_KERN_WARN
  278. "error sending event! return code %d\n",
  279. (int)hvrc);
  280. return;
  281. }
  282. /*
  283. * clear the used bit, zero the number of bytes in
  284. * this buffer, and move to the next buffer
  285. */
  286. clear_bit(nextbuf, &pi->used);
  287. pi->bufferBytes[nextbuf] = 0;
  288. nextbuf = (nextbuf + 1) % VIOCHAR_NUM_BUF;
  289. }
  290. /*
  291. * If we have emptied all the buffers, start at 0 again.
  292. * this will re-use any allocated buffers
  293. */
  294. if (pi->used == 0) {
  295. pi->curbuf = 0;
  296. if (pi->overflowMessage)
  297. pi->overflowMessage = 0;
  298. if (pi->tty) {
  299. tty_wakeup(pi->tty);
  300. }
  301. }
  302. vio_free_event_buffer(viomajorsubtype_chario, viochar);
  303. spin_unlock_irqrestore(&consolelock, flags);
  304. }
  305. /*
  306. * Our internal writer. Gets called both from the console device and
  307. * the tty device. the tty pointer will be NULL if called from the console.
  308. * Return total number of bytes "written".
  309. *
  310. * NOTE: Don't use printk in here because it gets nastily recursive. hvlog
  311. * can be used to log to the hypervisor buffer
  312. */
  313. static int internal_write(struct port_info *pi, const char *buf, size_t len)
  314. {
  315. HvLpEvent_Rc hvrc;
  316. size_t bleft;
  317. size_t curlen;
  318. const char *curbuf;
  319. unsigned long flags;
  320. struct viocharlpevent *viochar;
  321. /*
  322. * Write to the hvlog of inbound data are now done prior to
  323. * calling internal_write() since internal_write() is only called in
  324. * the event that an lp event path is active, which isn't the case for
  325. * logging attempts prior to console initialization.
  326. *
  327. * If there is already data queued for this port, send it prior to
  328. * attempting to send any new data.
  329. */
  330. if (pi->used)
  331. send_buffers(pi);
  332. spin_lock_irqsave(&consolelock, flags);
  333. viochar = vio_get_event_buffer(viomajorsubtype_chario);
  334. if (viochar == NULL) {
  335. spin_unlock_irqrestore(&consolelock, flags);
  336. hvlog("\n\rviocons: Can't get vio buffer in internal_write().");
  337. return -EAGAIN;
  338. }
  339. initDataEvent(viochar, pi->lp);
  340. curbuf = buf;
  341. bleft = len;
  342. while ((bleft > 0) && (pi->used == 0) &&
  343. ((pi->seq - pi->ack) < VIOCHAR_WINDOW)) {
  344. if (bleft > VIOCHAR_MAX_DATA)
  345. curlen = VIOCHAR_MAX_DATA;
  346. else
  347. curlen = bleft;
  348. viochar->event.xCorrelationToken = pi->seq++;
  349. memcpy(viochar->data, curbuf, curlen);
  350. viochar->len = curlen;
  351. viochar->event.xSizeMinus1 =
  352. offsetof(struct viocharlpevent, data) + curlen;
  353. hvrc = HvCallEvent_signalLpEvent(&viochar->event);
  354. if (hvrc) {
  355. hvlog("viocons: error sending event! %d\n", (int)hvrc);
  356. goto out;
  357. }
  358. curbuf += curlen;
  359. bleft -= curlen;
  360. }
  361. /* If we didn't send it all, buffer as much of it as we can. */
  362. if (bleft > 0)
  363. bleft -= buffer_add(pi, curbuf, bleft);
  364. out:
  365. vio_free_event_buffer(viomajorsubtype_chario, viochar);
  366. spin_unlock_irqrestore(&consolelock, flags);
  367. return len - bleft;
  368. }
  369. static struct port_info *get_port_data(struct tty_struct *tty)
  370. {
  371. unsigned long flags;
  372. struct port_info *pi;
  373. spin_lock_irqsave(&consolelock, flags);
  374. if (tty) {
  375. pi = (struct port_info *)tty->driver_data;
  376. if (!pi || viotty_paranoia_check(pi, tty->name,
  377. "get_port_data")) {
  378. pi = NULL;
  379. }
  380. } else
  381. /*
  382. * If this is the console device, use the lp from
  383. * the first port entry
  384. */
  385. pi = &port_info[0];
  386. spin_unlock_irqrestore(&consolelock, flags);
  387. return pi;
  388. }
  389. /*
  390. * Initialize the common fields in a charLpEvent
  391. */
  392. static void initDataEvent(struct viocharlpevent *viochar, HvLpIndex lp)
  393. {
  394. struct HvLpEvent *hev = &viochar->event;
  395. memset(viochar, 0, sizeof(struct viocharlpevent));
  396. hev->flags = HV_LP_EVENT_VALID | HV_LP_EVENT_DEFERRED_ACK |
  397. HV_LP_EVENT_INT;
  398. hev->xType = HvLpEvent_Type_VirtualIo;
  399. hev->xSubtype = viomajorsubtype_chario | viochardata;
  400. hev->xSourceLp = HvLpConfig_getLpIndex();
  401. hev->xTargetLp = lp;
  402. hev->xSizeMinus1 = sizeof(struct viocharlpevent);
  403. hev->xSourceInstanceId = viopath_sourceinst(lp);
  404. hev->xTargetInstanceId = viopath_targetinst(lp);
  405. }
  406. /*
  407. * early console device write
  408. */
  409. static void viocons_write_early(struct console *co, const char *s, unsigned count)
  410. {
  411. hvlogOutput(s, count);
  412. }
  413. /*
  414. * console device write
  415. */
  416. static void viocons_write(struct console *co, const char *s, unsigned count)
  417. {
  418. int index;
  419. int begin;
  420. struct port_info *pi;
  421. static const char cr = '\r';
  422. /*
  423. * Check port data first because the target LP might be valid but
  424. * simply not active, in which case we want to hvlog the output.
  425. */
  426. pi = get_port_data(NULL);
  427. if (pi == NULL) {
  428. hvlog("\n\rviocons_write: unable to get port data.");
  429. return;
  430. }
  431. hvlogOutput(s, count);
  432. if (!viopath_isactive(pi->lp))
  433. return;
  434. /*
  435. * Any newline character found will cause a
  436. * carriage return character to be emitted as well.
  437. */
  438. begin = 0;
  439. for (index = 0; index < count; index++) {
  440. if (s[index] == '\n') {
  441. /*
  442. * Newline found. Print everything up to and
  443. * including the newline
  444. */
  445. internal_write(pi, &s[begin], index - begin + 1);
  446. begin = index + 1;
  447. /* Emit a carriage return as well */
  448. internal_write(pi, &cr, 1);
  449. }
  450. }
  451. /* If any characters left to write, write them now */
  452. if ((index - begin) > 0)
  453. internal_write(pi, &s[begin], index - begin);
  454. }
  455. /*
  456. * Work out the device associate with this console
  457. */
  458. static struct tty_driver *viocons_device(struct console *c, int *index)
  459. {
  460. *index = c->index;
  461. return viotty_driver;
  462. }
  463. /*
  464. * console device I/O methods
  465. */
  466. static struct console viocons_early = {
  467. .name = "viocons",
  468. .write = viocons_write_early,
  469. .flags = CON_PRINTBUFFER,
  470. .index = -1,
  471. };
  472. static struct console viocons = {
  473. .name = "viocons",
  474. .write = viocons_write,
  475. .device = viocons_device,
  476. .flags = CON_PRINTBUFFER,
  477. .index = -1,
  478. };
  479. /*
  480. * TTY Open method
  481. */
  482. static int viotty_open(struct tty_struct *tty, struct file *filp)
  483. {
  484. int port;
  485. unsigned long flags;
  486. struct port_info *pi;
  487. port = tty->index;
  488. if ((port < 0) || (port >= VTTY_PORTS))
  489. return -ENODEV;
  490. spin_lock_irqsave(&consolelock, flags);
  491. pi = &port_info[port];
  492. /* If some other TTY is already connected here, reject the open */
  493. if ((pi->tty) && (pi->tty != tty)) {
  494. spin_unlock_irqrestore(&consolelock, flags);
  495. printk(VIOCONS_KERN_WARN
  496. "attempt to open device twice from different ttys\n");
  497. return -EBUSY;
  498. }
  499. tty->driver_data = pi;
  500. pi->tty = tty;
  501. spin_unlock_irqrestore(&consolelock, flags);
  502. return 0;
  503. }
  504. /*
  505. * TTY Close method
  506. */
  507. static void viotty_close(struct tty_struct *tty, struct file *filp)
  508. {
  509. unsigned long flags;
  510. struct port_info *pi;
  511. spin_lock_irqsave(&consolelock, flags);
  512. pi = (struct port_info *)tty->driver_data;
  513. if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_close")) {
  514. spin_unlock_irqrestore(&consolelock, flags);
  515. return;
  516. }
  517. if (tty->count == 1)
  518. pi->tty = NULL;
  519. spin_unlock_irqrestore(&consolelock, flags);
  520. }
  521. /*
  522. * TTY Write method
  523. */
  524. static int viotty_write(struct tty_struct *tty, const unsigned char *buf,
  525. int count)
  526. {
  527. struct port_info *pi;
  528. pi = get_port_data(tty);
  529. if (pi == NULL) {
  530. hvlog("\n\rviotty_write: no port data.");
  531. return -ENODEV;
  532. }
  533. if (viochar_is_console(pi))
  534. hvlogOutput(buf, count);
  535. /*
  536. * If the path to this LP is closed, don't bother doing anything more.
  537. * just dump the data on the floor and return count. For some reason
  538. * some user level programs will attempt to probe available tty's and
  539. * they'll attempt a viotty_write on an invalid port which maps to an
  540. * invalid target lp. If this is the case then ignore the
  541. * viotty_write call and, since the viopath isn't active to this
  542. * partition, return count.
  543. */
  544. if (!viopath_isactive(pi->lp))
  545. return count;
  546. return internal_write(pi, buf, count);
  547. }
  548. /*
  549. * TTY put_char method
  550. */
  551. static void viotty_put_char(struct tty_struct *tty, unsigned char ch)
  552. {
  553. struct port_info *pi;
  554. pi = get_port_data(tty);
  555. if (pi == NULL)
  556. return;
  557. /* This will append '\r' as well if the char is '\n' */
  558. if (viochar_is_console(pi))
  559. hvlogOutput(&ch, 1);
  560. if (viopath_isactive(pi->lp))
  561. internal_write(pi, &ch, 1);
  562. }
  563. /*
  564. * TTY write_room method
  565. */
  566. static int viotty_write_room(struct tty_struct *tty)
  567. {
  568. int i;
  569. int room = 0;
  570. struct port_info *pi;
  571. unsigned long flags;
  572. spin_lock_irqsave(&consolelock, flags);
  573. pi = (struct port_info *)tty->driver_data;
  574. if (!pi || viotty_paranoia_check(pi, tty->name, "viotty_write_room")) {
  575. spin_unlock_irqrestore(&consolelock, flags);
  576. return 0;
  577. }
  578. /* If no buffers are used, return the max size. */
  579. if (pi->used == 0) {
  580. spin_unlock_irqrestore(&consolelock, flags);
  581. return VIOCHAR_MAX_DATA * VIOCHAR_NUM_BUF;
  582. }
  583. /*
  584. * We retain the spinlock because we want to get an accurate
  585. * count and it can change on us between each operation if we
  586. * don't hold the spinlock.
  587. */
  588. for (i = 0; ((i < VIOCHAR_NUM_BUF) && (room < VIOCHAR_MAX_DATA)); i++)
  589. room += (VIOCHAR_MAX_DATA - pi->bufferBytes[i]);
  590. spin_unlock_irqrestore(&consolelock, flags);
  591. if (room > VIOCHAR_MAX_DATA)
  592. room = VIOCHAR_MAX_DATA;
  593. return room;
  594. }
  595. /*
  596. * TTY chars_in_buffer method
  597. */
  598. static int viotty_chars_in_buffer(struct tty_struct *tty)
  599. {
  600. return 0;
  601. }
  602. static int viotty_ioctl(struct tty_struct *tty, struct file *file,
  603. unsigned int cmd, unsigned long arg)
  604. {
  605. switch (cmd) {
  606. /*
  607. * the ioctls below read/set the flags usually shown in the leds
  608. * don't use them - they will go away without warning
  609. */
  610. case KDGETLED:
  611. case KDGKBLED:
  612. return put_user(0, (char *)arg);
  613. case KDSKBLED:
  614. return 0;
  615. }
  616. return n_tty_ioctl(tty, file, cmd, arg);
  617. }
  618. /*
  619. * Handle an open charLpEvent. Could be either interrupt or ack
  620. */
  621. static void vioHandleOpenEvent(struct HvLpEvent *event)
  622. {
  623. unsigned long flags;
  624. struct viocharlpevent *cevent = (struct viocharlpevent *)event;
  625. u8 port = cevent->virtual_device;
  626. struct port_info *pi;
  627. int reject = 0;
  628. if (hvlpevent_is_ack(event)) {
  629. if (port >= VTTY_PORTS)
  630. return;
  631. spin_lock_irqsave(&consolelock, flags);
  632. /* Got the lock, don't cause console output */
  633. pi = &port_info[port];
  634. if (event->xRc == HvLpEvent_Rc_Good) {
  635. pi->seq = pi->ack = 0;
  636. /*
  637. * This line allows connections from the primary
  638. * partition but once one is connected from the
  639. * primary partition nothing short of a reboot
  640. * of linux will allow access from the hosting
  641. * partition again without a required iSeries fix.
  642. */
  643. pi->lp = event->xTargetLp;
  644. }
  645. spin_unlock_irqrestore(&consolelock, flags);
  646. if (event->xRc != HvLpEvent_Rc_Good)
  647. printk(VIOCONS_KERN_WARN
  648. "handle_open_event: event->xRc == (%d).\n",
  649. event->xRc);
  650. if (event->xCorrelationToken != 0) {
  651. atomic_t *aptr= (atomic_t *)event->xCorrelationToken;
  652. atomic_set(aptr, 1);
  653. } else
  654. printk(VIOCONS_KERN_WARN
  655. "weird...got open ack without atomic\n");
  656. return;
  657. }
  658. /* This had better require an ack, otherwise complain */
  659. if (!hvlpevent_need_ack(event)) {
  660. printk(VIOCONS_KERN_WARN "viocharopen without ack bit!\n");
  661. return;
  662. }
  663. spin_lock_irqsave(&consolelock, flags);
  664. /* Got the lock, don't cause console output */
  665. /* Make sure this is a good virtual tty */
  666. if (port >= VTTY_PORTS) {
  667. event->xRc = HvLpEvent_Rc_SubtypeError;
  668. cevent->subtype_result_code = viorc_openRejected;
  669. /*
  670. * Flag state here since we can't printk while holding
  671. * a spinlock.
  672. */
  673. reject = 1;
  674. } else {
  675. pi = &port_info[port];
  676. if ((pi->lp != HvLpIndexInvalid) &&
  677. (pi->lp != event->xSourceLp)) {
  678. /*
  679. * If this is tty is already connected to a different
  680. * partition, fail.
  681. */
  682. event->xRc = HvLpEvent_Rc_SubtypeError;
  683. cevent->subtype_result_code = viorc_openRejected;
  684. reject = 2;
  685. } else {
  686. pi->lp = event->xSourceLp;
  687. event->xRc = HvLpEvent_Rc_Good;
  688. cevent->subtype_result_code = viorc_good;
  689. pi->seq = pi->ack = 0;
  690. reject = 0;
  691. }
  692. }
  693. spin_unlock_irqrestore(&consolelock, flags);
  694. if (reject == 1)
  695. printk(VIOCONS_KERN_WARN "open rejected: bad virtual tty.\n");
  696. else if (reject == 2)
  697. printk(VIOCONS_KERN_WARN
  698. "open rejected: console in exclusive use by another partition.\n");
  699. /* Return the acknowledgement */
  700. HvCallEvent_ackLpEvent(event);
  701. }
  702. /*
  703. * Handle a close charLpEvent. This should ONLY be an Interrupt because the
  704. * virtual console should never actually issue a close event to the hypervisor
  705. * because the virtual console never goes away. A close event coming from the
  706. * hypervisor simply means that there are no client consoles connected to the
  707. * virtual console.
  708. *
  709. * Regardless of the number of connections masqueraded on the other side of
  710. * the hypervisor ONLY ONE close event should be called to accompany the ONE
  711. * open event that is called. The close event should ONLY be called when NO
  712. * MORE connections (masqueraded or not) exist on the other side of the
  713. * hypervisor.
  714. */
  715. static void vioHandleCloseEvent(struct HvLpEvent *event)
  716. {
  717. unsigned long flags;
  718. struct viocharlpevent *cevent = (struct viocharlpevent *)event;
  719. u8 port = cevent->virtual_device;
  720. if (hvlpevent_is_int(event)) {
  721. if (port >= VTTY_PORTS) {
  722. printk(VIOCONS_KERN_WARN
  723. "close message from invalid virtual device.\n");
  724. return;
  725. }
  726. /* For closes, just mark the console partition invalid */
  727. spin_lock_irqsave(&consolelock, flags);
  728. /* Got the lock, don't cause console output */
  729. if (port_info[port].lp == event->xSourceLp)
  730. port_info[port].lp = HvLpIndexInvalid;
  731. spin_unlock_irqrestore(&consolelock, flags);
  732. printk(VIOCONS_KERN_INFO "close from %d\n", event->xSourceLp);
  733. } else
  734. printk(VIOCONS_KERN_WARN
  735. "got unexpected close acknowlegement\n");
  736. }
  737. /*
  738. * Handle a config charLpEvent. Could be either interrupt or ack
  739. */
  740. static void vioHandleConfig(struct HvLpEvent *event)
  741. {
  742. struct viocharlpevent *cevent = (struct viocharlpevent *)event;
  743. HvCall_writeLogBuffer(cevent->data, cevent->len);
  744. if (cevent->data[0] == 0x01)
  745. printk(VIOCONS_KERN_INFO "window resized to %d: %d: %d: %d\n",
  746. cevent->data[1], cevent->data[2],
  747. cevent->data[3], cevent->data[4]);
  748. else
  749. printk(VIOCONS_KERN_WARN "unknown config event\n");
  750. }
  751. /*
  752. * Handle a data charLpEvent.
  753. */
  754. static void vioHandleData(struct HvLpEvent *event)
  755. {
  756. struct tty_struct *tty;
  757. unsigned long flags;
  758. struct viocharlpevent *cevent = (struct viocharlpevent *)event;
  759. struct port_info *pi;
  760. int index;
  761. int num_pushed;
  762. u8 port = cevent->virtual_device;
  763. if (port >= VTTY_PORTS) {
  764. printk(VIOCONS_KERN_WARN "data on invalid virtual device %d\n",
  765. port);
  766. return;
  767. }
  768. /*
  769. * Hold the spinlock so that we don't take an interrupt that
  770. * changes tty between the time we fetch the port_info
  771. * pointer and the time we paranoia check.
  772. */
  773. spin_lock_irqsave(&consolelock, flags);
  774. pi = &port_info[port];
  775. /*
  776. * Change 05/01/2003 - Ryan Arnold: If a partition other than
  777. * the current exclusive partition tries to send us data
  778. * events then just drop them on the floor because we don't
  779. * want his stinking data. He isn't authorized to receive
  780. * data because he wasn't the first one to get the console,
  781. * therefore he shouldn't be allowed to send data either.
  782. * This will work without an iSeries fix.
  783. */
  784. if (pi->lp != event->xSourceLp) {
  785. spin_unlock_irqrestore(&consolelock, flags);
  786. return;
  787. }
  788. tty = pi->tty;
  789. if (tty == NULL) {
  790. spin_unlock_irqrestore(&consolelock, flags);
  791. printk(VIOCONS_KERN_WARN "no tty for virtual device %d\n",
  792. port);
  793. return;
  794. }
  795. if (tty->magic != TTY_MAGIC) {
  796. spin_unlock_irqrestore(&consolelock, flags);
  797. printk(VIOCONS_KERN_WARN "tty bad magic\n");
  798. return;
  799. }
  800. /*
  801. * Just to be paranoid, make sure the tty points back to this port
  802. */
  803. pi = (struct port_info *)tty->driver_data;
  804. if (!pi || viotty_paranoia_check(pi, tty->name, "vioHandleData")) {
  805. spin_unlock_irqrestore(&consolelock, flags);
  806. return;
  807. }
  808. spin_unlock_irqrestore(&consolelock, flags);
  809. /*
  810. * Change 07/21/2003 - Ryan Arnold: functionality added to
  811. * support sysrq utilizing ^O as the sysrq key. The sysrq
  812. * functionality will only work if built into the kernel and
  813. * then only if sysrq is enabled through the proc filesystem.
  814. */
  815. num_pushed = 0;
  816. for (index = 0; index < cevent->len; index++) {
  817. #ifdef CONFIG_MAGIC_SYSRQ
  818. if (sysrq_enabled) {
  819. /* 0x0f is the ascii character for ^O */
  820. if (cevent->data[index] == '\x0f') {
  821. vio_sysrq_pressed = 1;
  822. /*
  823. * continue because we don't want to add
  824. * the sysrq key into the data string.
  825. */
  826. continue;
  827. } else if (vio_sysrq_pressed) {
  828. handle_sysrq(cevent->data[index], tty);
  829. vio_sysrq_pressed = 0;
  830. /*
  831. * continue because we don't want to add
  832. * the sysrq sequence into the data string.
  833. */
  834. continue;
  835. }
  836. }
  837. #endif
  838. /*
  839. * The sysrq sequence isn't included in this check if
  840. * sysrq is enabled and compiled into the kernel because
  841. * the sequence will never get inserted into the buffer.
  842. * Don't attempt to copy more data into the buffer than we
  843. * have room for because it would fail without indication.
  844. */
  845. if(tty_insert_flip_char(tty, cevent->data[index], TTY_NORMAL) == 0) {
  846. printk(VIOCONS_KERN_WARN "input buffer overflow!\n");
  847. break;
  848. }
  849. num_pushed++;
  850. }
  851. if (num_pushed)
  852. tty_flip_buffer_push(tty);
  853. }
  854. /*
  855. * Handle an ack charLpEvent.
  856. */
  857. static void vioHandleAck(struct HvLpEvent *event)
  858. {
  859. struct viocharlpevent *cevent = (struct viocharlpevent *)event;
  860. unsigned long flags;
  861. u8 port = cevent->virtual_device;
  862. if (port >= VTTY_PORTS) {
  863. printk(VIOCONS_KERN_WARN "data on invalid virtual device\n");
  864. return;
  865. }
  866. spin_lock_irqsave(&consolelock, flags);
  867. port_info[port].ack = event->xCorrelationToken;
  868. spin_unlock_irqrestore(&consolelock, flags);
  869. if (port_info[port].used)
  870. send_buffers(&port_info[port]);
  871. }
  872. /*
  873. * Handle charLpEvents and route to the appropriate routine
  874. */
  875. static void vioHandleCharEvent(struct HvLpEvent *event)
  876. {
  877. int charminor;
  878. if (event == NULL)
  879. return;
  880. charminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
  881. switch (charminor) {
  882. case viocharopen:
  883. vioHandleOpenEvent(event);
  884. break;
  885. case viocharclose:
  886. vioHandleCloseEvent(event);
  887. break;
  888. case viochardata:
  889. vioHandleData(event);
  890. break;
  891. case viocharack:
  892. vioHandleAck(event);
  893. break;
  894. case viocharconfig:
  895. vioHandleConfig(event);
  896. break;
  897. default:
  898. if (hvlpevent_is_int(event) && hvlpevent_need_ack(event)) {
  899. event->xRc = HvLpEvent_Rc_InvalidSubtype;
  900. HvCallEvent_ackLpEvent(event);
  901. }
  902. }
  903. }
  904. /*
  905. * Send an open event
  906. */
  907. static int send_open(HvLpIndex remoteLp, void *sem)
  908. {
  909. return HvCallEvent_signalLpEventFast(remoteLp,
  910. HvLpEvent_Type_VirtualIo,
  911. viomajorsubtype_chario | viocharopen,
  912. HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
  913. viopath_sourceinst(remoteLp),
  914. viopath_targetinst(remoteLp),
  915. (u64)(unsigned long)sem, VIOVERSION << 16,
  916. 0, 0, 0, 0);
  917. }
  918. static const struct tty_operations serial_ops = {
  919. .open = viotty_open,
  920. .close = viotty_close,
  921. .write = viotty_write,
  922. .put_char = viotty_put_char,
  923. .write_room = viotty_write_room,
  924. .chars_in_buffer = viotty_chars_in_buffer,
  925. .ioctl = viotty_ioctl,
  926. };
  927. static int __init viocons_init2(void)
  928. {
  929. atomic_t wait_flag;
  930. int rc;
  931. /* +2 for fudge */
  932. rc = viopath_open(HvLpConfig_getPrimaryLpIndex(),
  933. viomajorsubtype_chario, VIOCHAR_WINDOW + 2);
  934. if (rc)
  935. printk(VIOCONS_KERN_WARN "error opening to primary %d\n", rc);
  936. if (viopath_hostLp == HvLpIndexInvalid)
  937. vio_set_hostlp();
  938. /*
  939. * And if the primary is not the same as the hosting LP, open to the
  940. * hosting lp
  941. */
  942. if ((viopath_hostLp != HvLpIndexInvalid) &&
  943. (viopath_hostLp != HvLpConfig_getPrimaryLpIndex())) {
  944. printk(VIOCONS_KERN_INFO "open path to hosting (%d)\n",
  945. viopath_hostLp);
  946. rc = viopath_open(viopath_hostLp, viomajorsubtype_chario,
  947. VIOCHAR_WINDOW + 2); /* +2 for fudge */
  948. if (rc)
  949. printk(VIOCONS_KERN_WARN
  950. "error opening to partition %d: %d\n",
  951. viopath_hostLp, rc);
  952. }
  953. if (vio_setHandler(viomajorsubtype_chario, vioHandleCharEvent) < 0)
  954. printk(VIOCONS_KERN_WARN
  955. "error seting handler for console events!\n");
  956. /*
  957. * First, try to open the console to the hosting lp.
  958. * Wait on a semaphore for the response.
  959. */
  960. atomic_set(&wait_flag, 0);
  961. if ((viopath_isactive(viopath_hostLp)) &&
  962. (send_open(viopath_hostLp, (void *)&wait_flag) == 0)) {
  963. printk(VIOCONS_KERN_INFO "hosting partition %d\n",
  964. viopath_hostLp);
  965. while (atomic_read(&wait_flag) == 0)
  966. mb();
  967. atomic_set(&wait_flag, 0);
  968. }
  969. /*
  970. * If we don't have an active console, try the primary
  971. */
  972. if ((!viopath_isactive(port_info[0].lp)) &&
  973. (viopath_isactive(HvLpConfig_getPrimaryLpIndex())) &&
  974. (send_open(HvLpConfig_getPrimaryLpIndex(), (void *)&wait_flag)
  975. == 0)) {
  976. printk(VIOCONS_KERN_INFO "opening console to primary partition\n");
  977. while (atomic_read(&wait_flag) == 0)
  978. mb();
  979. }
  980. /* Initialize the tty_driver structure */
  981. viotty_driver = alloc_tty_driver(VTTY_PORTS);
  982. viotty_driver->owner = THIS_MODULE;
  983. viotty_driver->driver_name = "vioconsole";
  984. viotty_driver->name = "tty";
  985. viotty_driver->name_base = 1;
  986. viotty_driver->major = TTY_MAJOR;
  987. viotty_driver->minor_start = 1;
  988. viotty_driver->type = TTY_DRIVER_TYPE_CONSOLE;
  989. viotty_driver->subtype = 1;
  990. viotty_driver->init_termios = tty_std_termios;
  991. viotty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
  992. tty_set_operations(viotty_driver, &serial_ops);
  993. if (tty_register_driver(viotty_driver)) {
  994. printk(VIOCONS_KERN_WARN "couldn't register console driver\n");
  995. put_tty_driver(viotty_driver);
  996. viotty_driver = NULL;
  997. }
  998. unregister_console(&viocons_early);
  999. register_console(&viocons);
  1000. return 0;
  1001. }
  1002. static int __init viocons_init(void)
  1003. {
  1004. int i;
  1005. printk(VIOCONS_KERN_INFO "registering console\n");
  1006. for (i = 0; i < VTTY_PORTS; i++) {
  1007. port_info[i].lp = HvLpIndexInvalid;
  1008. port_info[i].magic = VIOTTY_MAGIC;
  1009. }
  1010. HvCall_setLogBufferFormatAndCodepage(HvCall_LogBuffer_ASCII, 437);
  1011. add_preferred_console("viocons", 0, NULL);
  1012. register_console(&viocons_early);
  1013. return 0;
  1014. }
  1015. console_initcall(viocons_init);
  1016. module_init(viocons_init2);