viocons.c 30 KB

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