viocons.c 30 KB

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