hwc_rw.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:48k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  *  drivers/s390/char/hwc_rw.c
  3.  *     driver: reading from and writing to system console on S/390 via HWC
  4.  *
  5.  *  S390 version
  6.  *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
  7.  *    Author(s): Martin Peschke <mpeschke@de.ibm.com>
  8.  *
  9.  * 
  10.  *
  11.  * 
  12.  * 
  13.  * 
  14.  */
  15. #include <linux/kernel.h>
  16. #include <linux/string.h>
  17. #include <linux/errno.h>
  18. #include <linux/ctype.h>
  19. #include <linux/mm.h>
  20. #include <linux/timer.h>
  21. #include <linux/bootmem.h>
  22. #include <linux/module.h>
  23. #include <asm/ebcdic.h>
  24. #include <asm/uaccess.h>
  25. #include <asm/types.h>
  26. #include <asm/bitops.h>
  27. #include <asm/setup.h>
  28. #include <asm/page.h>
  29. #include <asm/s390_ext.h>
  30. #include <asm/irq.h>
  31. #ifndef MIN
  32. #define MIN(a,b) (((a<b) ? a : b))
  33. #endif
  34. extern void ctrl_alt_del (void);
  35. #define HWC_RW_PRINT_HEADER "hwc low level driver: "
  36. #define  USE_VM_DETECTION
  37. #define  DEFAULT_CASE_DELIMITER '%'
  38. #undef DUMP_HWC_INIT_ERROR
  39. #undef DUMP_HWC_WRITE_ERROR
  40. #undef DUMP_HWC_WRITE_LIST_ERROR
  41. #undef DUMP_HWC_READ_ERROR
  42. #undef DUMP_HWCB_INPUT
  43. #undef BUFFER_STRESS_TEST
  44. typedef struct {
  45. unsigned char *next;
  46. unsigned short int mto_char_sum;
  47. unsigned char mto_number;
  48. unsigned char times_lost;
  49. unsigned short int mto_number_lost;
  50. unsigned long int mto_char_sum_lost;
  51. } __attribute__ ((packed)) 
  52. hwcb_list_t;
  53. #define MAX_HWCB_ROOM (PAGE_SIZE - sizeof(hwcb_list_t))
  54. #define MAX_MESSAGE_SIZE (MAX_HWCB_ROOM - sizeof(write_hwcb_t))
  55. #define BUF_HWCB hwc_data.hwcb_list_tail
  56. #define OUT_HWCB hwc_data.hwcb_list_head
  57. #define ALL_HWCB_MTO hwc_data.mto_number
  58. #define ALL_HWCB_CHAR hwc_data.mto_char_sum
  59. #define _LIST(hwcb) ((hwcb_list_t*)(&(hwcb)[PAGE_SIZE-sizeof(hwcb_list_t)]))
  60. #define _HWCB_CHAR(hwcb) (_LIST(hwcb)->mto_char_sum)
  61. #define _HWCB_MTO(hwcb) (_LIST(hwcb)->mto_number)
  62. #define _HWCB_CHAR_LOST(hwcb) (_LIST(hwcb)->mto_char_sum_lost)
  63. #define _HWCB_MTO_LOST(hwcb) (_LIST(hwcb)->mto_number_lost)
  64. #define _HWCB_TIMES_LOST(hwcb) (_LIST(hwcb)->times_lost)
  65. #define _HWCB_NEXT(hwcb) (_LIST(hwcb)->next)
  66. #define BUF_HWCB_CHAR _HWCB_CHAR(BUF_HWCB)
  67. #define BUF_HWCB_MTO _HWCB_MTO(BUF_HWCB)
  68. #define BUF_HWCB_NEXT _HWCB_NEXT(BUF_HWCB)
  69. #define OUT_HWCB_CHAR _HWCB_CHAR(OUT_HWCB)
  70. #define OUT_HWCB_MTO _HWCB_MTO(OUT_HWCB)
  71. #define OUT_HWCB_NEXT _HWCB_NEXT(OUT_HWCB)
  72. #define BUF_HWCB_CHAR_LOST _HWCB_CHAR_LOST(BUF_HWCB)
  73. #define BUF_HWCB_MTO_LOST _HWCB_MTO_LOST(BUF_HWCB)
  74. #define OUT_HWCB_CHAR_LOST _HWCB_CHAR_LOST(OUT_HWCB)
  75. #define OUT_HWCB_MTO_LOST _HWCB_MTO_LOST(OUT_HWCB)
  76. #define BUF_HWCB_TIMES_LOST _HWCB_TIMES_LOST(BUF_HWCB)
  77. #include  "hwc.h"
  78. #define __HWC_RW_C__
  79. #include "hwc_rw.h"
  80. #undef __HWC_RW_C__
  81. static unsigned char _obuf[MAX_HWCB_ROOM];
  82. static unsigned char
  83.  _page[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
  84. typedef unsigned long kmem_pages_t;
  85. #define MAX_KMEM_PAGES (sizeof(kmem_pages_t) << 3)
  86. #define HWC_WTIMER_RUNS 1
  87. #define HWC_FLUSH 2
  88. #define HWC_INIT 4
  89. #define HWC_BROKEN 8
  90. #define HWC_INTERRUPT 16
  91. #define HWC_PTIMER_RUNS 32
  92. static struct {
  93. hwc_ioctls_t ioctls;
  94. hwc_ioctls_t init_ioctls;
  95. unsigned char *hwcb_list_head;
  96. unsigned char *hwcb_list_tail;
  97. unsigned short int mto_number;
  98. unsigned int mto_char_sum;
  99. unsigned char hwcb_count;
  100. unsigned long kmem_start;
  101. unsigned long kmem_end;
  102. kmem_pages_t kmem_pages;
  103. unsigned char *obuf;
  104. unsigned short int obuf_cursor;
  105. unsigned short int obuf_count;
  106. unsigned short int obuf_start;
  107. unsigned char *page;
  108. u32 current_servc;
  109. unsigned char *current_hwcb;
  110. unsigned char write_nonprio:1;
  111. unsigned char write_prio:1;
  112. unsigned char read_nonprio:1;
  113. unsigned char read_prio:1;
  114. unsigned char read_statechange:1;
  115. unsigned char sig_quiesce:1;
  116. unsigned char flags;
  117. hwc_high_level_calls_t *calls;
  118. hwc_request_t *request;
  119. spinlock_t lock;
  120. struct timer_list write_timer;
  121. struct timer_list poll_timer;
  122. } hwc_data =
  123. {
  124. {
  125. },
  126. {
  127. 8,
  128.     0,
  129.     80,
  130.     1,
  131.     MAX_KMEM_PAGES,
  132.     MAX_KMEM_PAGES,
  133.     0,
  134.     0x6c
  135. },
  136.     NULL,
  137.     NULL,
  138.     0,
  139.     0,
  140.     0,
  141.     0,
  142.     0,
  143.     0,
  144.     _obuf,
  145.     0,
  146.     0,
  147.     0,
  148.     _page,
  149.     0,
  150.     NULL,
  151.     0,
  152.     0,
  153.     0,
  154.     0,
  155.     0,
  156.     0,
  157.     0,
  158.     NULL,
  159.     NULL
  160. };
  161. static unsigned long cr0 __attribute__ ((aligned (8)));
  162. static unsigned long cr0_save __attribute__ ((aligned (8)));
  163. static unsigned char psw_mask __attribute__ ((aligned (8)));
  164. static ext_int_info_t ext_int_info_hwc;
  165. #define DELAYED_WRITE 0
  166. #define IMMEDIATE_WRITE 1
  167. static signed int do_hwc_write (int from_user, unsigned char *,
  168. unsigned int,
  169. unsigned char);
  170. unsigned char hwc_ip_buf[512];
  171. static asmlinkage int 
  172. internal_print (char write_time, char *fmt,...)
  173. {
  174. va_list args;
  175. int i;
  176. va_start (args, fmt);
  177. i = vsprintf (hwc_ip_buf, fmt, args);
  178. va_end (args);
  179. return do_hwc_write (0, hwc_ip_buf, i, write_time);
  180. }
  181. int 
  182. hwc_printk (const char *fmt,...)
  183. {
  184. va_list args;
  185. int i;
  186. unsigned long flags;
  187. int retval;
  188. spin_lock_irqsave (&hwc_data.lock, flags);
  189. i = vsprintf (hwc_ip_buf, fmt, args);
  190. va_end (args);
  191. retval = do_hwc_write (0, hwc_ip_buf, i, IMMEDIATE_WRITE);
  192. spin_unlock_irqrestore (&hwc_data.lock, flags);
  193. return retval;
  194. }
  195. #ifdef DUMP_HWCB_INPUT
  196. static void 
  197. dump_storage_area (unsigned char *area, unsigned short int count)
  198. {
  199. unsigned short int index;
  200. ioctl_nl_t old_final_nl;
  201. if (!area || !count)
  202. return;
  203. old_final_nl = hwc_data.ioctls.final_nl;
  204. hwc_data.ioctls.final_nl = 1;
  205. internal_print (DELAYED_WRITE, "n%8x   ", area);
  206. for (index = 0; index < count; index++) {
  207. if (area[index] <= 0xF)
  208. internal_print (DELAYED_WRITE, "0%x", area[index]);
  209. else
  210. internal_print (DELAYED_WRITE, "%x", area[index]);
  211. if ((index & 0xF) == 0xF)
  212. internal_print (DELAYED_WRITE, "n%8x   ",
  213. &area[index + 1]);
  214. else if ((index & 3) == 3)
  215. internal_print (DELAYED_WRITE, " ");
  216. }
  217. internal_print (IMMEDIATE_WRITE, "n");
  218. hwc_data.ioctls.final_nl = old_final_nl;
  219. }
  220. #endif
  221. static inline u32 
  222. service_call (
  223.      u32 hwc_command_word,
  224.      unsigned char hwcb[])
  225. {
  226. unsigned int condition_code = 1;
  227. __asm__ __volatile__ ("L 1, 0(%0) nt"
  228.       "LRA 2, 0(%1) nt"
  229.       ".long 0xB2200012 nt"
  230.       :
  231.       :"a" (&hwc_command_word), "a" (hwcb)
  232.       :"1", "2", "memory");
  233. __asm__ __volatile__ ("IPM %0 nt"
  234.       "SRL %0, 28 nt"
  235.       :"=r" (condition_code));
  236. return condition_code;
  237. }
  238. static inline unsigned long 
  239. hwc_ext_int_param (void)
  240. {
  241. u32 param;
  242. __asm__ __volatile__ ("L %0,128nt"
  243.       :"=r" (param));
  244. return (unsigned long) param;
  245. }
  246. static int 
  247. prepare_write_hwcb (void)
  248. {
  249. write_hwcb_t *hwcb;
  250. if (!BUF_HWCB)
  251. return -ENOMEM;
  252. BUF_HWCB_MTO = 0;
  253. BUF_HWCB_CHAR = 0;
  254. hwcb = (write_hwcb_t *) BUF_HWCB;
  255. memcpy (hwcb, &write_hwcb_template, sizeof (write_hwcb_t));
  256. return 0;
  257. }
  258. static int 
  259. sane_write_hwcb (void)
  260. {
  261. unsigned short int lost_msg;
  262. unsigned int lost_char;
  263. unsigned char lost_hwcb;
  264. unsigned char *bad_addr;
  265. unsigned long page;
  266. int page_nr;
  267. if (!OUT_HWCB)
  268. return -ENOMEM;
  269. if ((unsigned long) OUT_HWCB & 0xFFF) {
  270. bad_addr = OUT_HWCB;
  271. #ifdef DUMP_HWC_WRITE_LIST_ERROR
  272. __asm__ ("LHI 1,0xe30nt"
  273.  "LRA 2,0(%0) nt"
  274.  "J .+0 nt"
  275.       :
  276.       :  "a" (bad_addr)
  277.       :  "1", "2");
  278. #endif
  279. hwc_data.kmem_pages = 0;
  280. if ((unsigned long) BUF_HWCB & 0xFFF) {
  281. lost_hwcb = hwc_data.hwcb_count;
  282. lost_msg = ALL_HWCB_MTO;
  283. lost_char = ALL_HWCB_CHAR;
  284. OUT_HWCB = NULL;
  285. BUF_HWCB = NULL;
  286. ALL_HWCB_MTO = 0;
  287. ALL_HWCB_CHAR = 0;
  288. hwc_data.hwcb_count = 0;
  289. } else {
  290. lost_hwcb = hwc_data.hwcb_count - 1;
  291. lost_msg = ALL_HWCB_MTO - BUF_HWCB_MTO;
  292. lost_char = ALL_HWCB_CHAR - BUF_HWCB_CHAR;
  293. OUT_HWCB = BUF_HWCB;
  294. ALL_HWCB_MTO = BUF_HWCB_MTO;
  295. ALL_HWCB_CHAR = BUF_HWCB_CHAR;
  296. hwc_data.hwcb_count = 1;
  297. page = (unsigned long) BUF_HWCB;
  298. if (page >= hwc_data.kmem_start &&
  299.     page <= hwc_data.kmem_end) {
  300. page_nr = (int)
  301.     ((page - hwc_data.kmem_start) >> 12);
  302. set_bit (page_nr, &hwc_data.kmem_pages);
  303. }
  304. }
  305. internal_print (
  306.        DELAYED_WRITE,
  307.        HWC_RW_PRINT_HEADER
  308.        "found invalid HWCB at address 0x%lx. List corrupted. "
  309.    "Lost %i HWCBs with %i characters within up to %i "
  310.    "messages. Saved %i HWCB with last %i characters i"
  311.        "within up to %i messages.n",
  312.        (unsigned long) bad_addr,
  313.        lost_hwcb, lost_char, lost_msg,
  314.        hwc_data.hwcb_count,
  315.        ALL_HWCB_CHAR, ALL_HWCB_MTO);
  316. }
  317. return 0;
  318. }
  319. static int 
  320. reuse_write_hwcb (void)
  321. {
  322. int retval;
  323. if (hwc_data.hwcb_count < 2)
  324. #ifdef DUMP_HWC_WRITE_LIST_ERROR
  325. __asm__ ("LHI 1,0xe31nt"
  326.  "LRA 2,0(%0)nt"
  327.  "LRA 3,0(%1)nt"
  328.  "J .+0 nt"
  329.       :
  330.       :  "a" (BUF_HWCB), "a" (OUT_HWCB)
  331.       :  "1", "2", "3");
  332. #else
  333. return -EPERM;
  334. #endif
  335. if (hwc_data.current_hwcb == OUT_HWCB) {
  336. if (hwc_data.hwcb_count > 2) {
  337. BUF_HWCB_NEXT = OUT_HWCB_NEXT;
  338. BUF_HWCB = OUT_HWCB_NEXT;
  339. OUT_HWCB_NEXT = BUF_HWCB_NEXT;
  340. BUF_HWCB_NEXT = NULL;
  341. }
  342. } else {
  343. BUF_HWCB_NEXT = OUT_HWCB;
  344. BUF_HWCB = OUT_HWCB;
  345. OUT_HWCB = OUT_HWCB_NEXT;
  346. BUF_HWCB_NEXT = NULL;
  347. }
  348. BUF_HWCB_TIMES_LOST += 1;
  349. BUF_HWCB_CHAR_LOST += BUF_HWCB_CHAR;
  350. BUF_HWCB_MTO_LOST += BUF_HWCB_MTO;
  351. ALL_HWCB_MTO -= BUF_HWCB_MTO;
  352. ALL_HWCB_CHAR -= BUF_HWCB_CHAR;
  353. retval = prepare_write_hwcb ();
  354. if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb)
  355. internal_print (
  356.        DELAYED_WRITE,
  357.        HWC_RW_PRINT_HEADER
  358.        "reached my own limit of "
  359.     "allowed buffer space for output (%i HWCBs = %li "
  360.   "bytes), skipped content of oldest HWCB %i time(s) "
  361.        "(%i lines = %i characters)n",
  362.        hwc_data.ioctls.max_hwcb,
  363.        hwc_data.ioctls.max_hwcb * PAGE_SIZE,
  364.        BUF_HWCB_TIMES_LOST,
  365.        BUF_HWCB_MTO_LOST,
  366.        BUF_HWCB_CHAR_LOST);
  367. else
  368. internal_print (
  369.        DELAYED_WRITE,
  370.        HWC_RW_PRINT_HEADER
  371.        "page allocation failed, "
  372.    "could not expand buffer for output (currently in "
  373.      "use: %i HWCBs = %li bytes), skipped content of "
  374. "oldest HWCB %i time(s) (%i lines = %i characters)n",
  375.        hwc_data.hwcb_count,
  376.        hwc_data.hwcb_count * PAGE_SIZE,
  377.        BUF_HWCB_TIMES_LOST,
  378.        BUF_HWCB_MTO_LOST,
  379.        BUF_HWCB_CHAR_LOST);
  380. return retval;
  381. }
  382. static int 
  383. allocate_write_hwcb (void)
  384. {
  385. unsigned char *page;
  386. int page_nr;
  387. if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb)
  388. return -ENOMEM;
  389. page_nr = find_first_zero_bit (&hwc_data.kmem_pages, MAX_KMEM_PAGES);
  390. if (page_nr < hwc_data.ioctls.kmem_hwcb) {
  391. page = (unsigned char *)
  392.     (hwc_data.kmem_start + (page_nr << 12));
  393. set_bit (page_nr, &hwc_data.kmem_pages);
  394. } else
  395. page = (unsigned char *) __get_free_page (GFP_ATOMIC | GFP_DMA);
  396. if (!page)
  397. return -ENOMEM;
  398. if (!OUT_HWCB)
  399. OUT_HWCB = page;
  400. else
  401. BUF_HWCB_NEXT = page;
  402. BUF_HWCB = page;
  403. BUF_HWCB_NEXT = NULL;
  404. hwc_data.hwcb_count++;
  405. prepare_write_hwcb ();
  406. BUF_HWCB_TIMES_LOST = 0;
  407. BUF_HWCB_MTO_LOST = 0;
  408. BUF_HWCB_CHAR_LOST = 0;
  409. #ifdef BUFFER_STRESS_TEST
  410. internal_print (
  411.        DELAYED_WRITE,
  412.        "*** " HWC_RW_PRINT_HEADER
  413.     "page #%i at 0x%x for buffering allocated. ***n",
  414.        hwc_data.hwcb_count, page);
  415. #endif
  416. return 0;
  417. }
  418. static int 
  419. release_write_hwcb (void)
  420. {
  421. unsigned long page;
  422. int page_nr;
  423. if (!hwc_data.hwcb_count)
  424. return -ENODATA;
  425. if (hwc_data.hwcb_count == 1) {
  426. prepare_write_hwcb ();
  427. ALL_HWCB_CHAR = 0;
  428. ALL_HWCB_MTO = 0;
  429. BUF_HWCB_TIMES_LOST = 0;
  430. BUF_HWCB_MTO_LOST = 0;
  431. BUF_HWCB_CHAR_LOST = 0;
  432. } else {
  433. page = (unsigned long) OUT_HWCB;
  434. ALL_HWCB_MTO -= OUT_HWCB_MTO;
  435. ALL_HWCB_CHAR -= OUT_HWCB_CHAR;
  436. hwc_data.hwcb_count--;
  437. OUT_HWCB = OUT_HWCB_NEXT;
  438. if (page >= hwc_data.kmem_start &&
  439.     page <= hwc_data.kmem_end) {
  440. /*memset((void *) page, 0, PAGE_SIZE); */
  441. page_nr = (int) ((page - hwc_data.kmem_start) >> 12);
  442. clear_bit (page_nr, &hwc_data.kmem_pages);
  443. } else
  444. free_page (page);
  445. #ifdef BUFFER_STRESS_TEST
  446. internal_print (
  447.        DELAYED_WRITE,
  448.        "*** " HWC_RW_PRINT_HEADER
  449.  "page at 0x%x released, %i pages still in use ***n",
  450.        page, hwc_data.hwcb_count);
  451. #endif
  452. }
  453. return 0;
  454. }
  455. static int 
  456. add_mto (
  457. unsigned char *message,
  458. unsigned short int count)
  459. {
  460. unsigned short int mto_size;
  461. write_hwcb_t *hwcb;
  462. mto_t *mto;
  463. void *dest;
  464. if (!BUF_HWCB)
  465. return -ENOMEM;
  466. if (BUF_HWCB == hwc_data.current_hwcb)
  467. return -ENOMEM;
  468. mto_size = sizeof (mto_t) + count;
  469. hwcb = (write_hwcb_t *) BUF_HWCB;
  470. if ((MAX_HWCB_ROOM - hwcb->length) < mto_size)
  471. return -ENOMEM;
  472. mto = (mto_t *) (((unsigned long) hwcb) + hwcb->length);
  473. memcpy (mto, &mto_template, sizeof (mto_t));
  474. dest = (void *) (((unsigned long) mto) + sizeof (mto_t));
  475. memcpy (dest, message, count);
  476. mto->length += count;
  477. hwcb->length += mto_size;
  478. hwcb->msgbuf.length += mto_size;
  479. hwcb->msgbuf.mdb.length += mto_size;
  480. BUF_HWCB_MTO++;
  481. ALL_HWCB_MTO++;
  482. BUF_HWCB_CHAR += count;
  483. ALL_HWCB_CHAR += count;
  484. return count;
  485. }
  486. static int write_event_data_1 (void);
  487. static void 
  488. do_poll_hwc (unsigned long data)
  489. {
  490. unsigned long flags;
  491. spin_lock_irqsave (&hwc_data.lock, flags);
  492. write_event_data_1 ();
  493. spin_unlock_irqrestore (&hwc_data.lock, flags);
  494. }
  495. void 
  496. start_poll_hwc (void)
  497. {
  498. init_timer (&hwc_data.poll_timer);
  499. hwc_data.poll_timer.function = do_poll_hwc;
  500. hwc_data.poll_timer.data = (unsigned long) NULL;
  501. hwc_data.poll_timer.expires = jiffies + 2 * HZ;
  502. add_timer (&hwc_data.poll_timer);
  503. hwc_data.flags |= HWC_PTIMER_RUNS;
  504. }
  505. static int 
  506. write_event_data_1 (void)
  507. {
  508. unsigned short int condition_code;
  509. int retval;
  510. write_hwcb_t *hwcb = (write_hwcb_t *) OUT_HWCB;
  511. if ((!hwc_data.write_prio) &&
  512.     (!hwc_data.write_nonprio) &&
  513.     hwc_data.read_statechange)
  514. return -EOPNOTSUPP;
  515. if (hwc_data.current_servc)
  516. return -EBUSY;
  517. retval = sane_write_hwcb ();
  518. if (retval < 0)
  519. return -EIO;
  520. if (!OUT_HWCB_MTO)
  521. return -ENODATA;
  522. if (!hwc_data.write_nonprio && hwc_data.write_prio)
  523. hwcb->msgbuf.type = ET_PMsgCmd;
  524. else
  525. hwcb->msgbuf.type = ET_Msg;
  526. condition_code = service_call (HWC_CMDW_WRITEDATA, OUT_HWCB);
  527. #ifdef DUMP_HWC_WRITE_ERROR
  528. if (condition_code != HWC_COMMAND_INITIATED)
  529. __asm__ ("LHI 1,0xe20nt"
  530.  "L 2,0(%0)nt"
  531.  "LRA 3,0(%1)nt"
  532.  "J .+0 nt"
  533.       :
  534.       :  "a" (&condition_code), "a" (OUT_HWCB)
  535.       :  "1", "2", "3");
  536. #endif
  537. switch (condition_code) {
  538. case HWC_COMMAND_INITIATED:
  539. hwc_data.current_servc = HWC_CMDW_WRITEDATA;
  540. hwc_data.current_hwcb = OUT_HWCB;
  541. retval = condition_code;
  542. break;
  543. case HWC_BUSY:
  544. retval = -EBUSY;
  545. break;
  546. case HWC_NOT_OPERATIONAL:
  547. start_poll_hwc ();
  548. default:
  549. retval = -EIO;
  550. }
  551. return retval;
  552. }
  553. static void 
  554. flush_hwcbs (void)
  555. {
  556. while (hwc_data.hwcb_count > 1)
  557. release_write_hwcb ();
  558. release_write_hwcb ();
  559. hwc_data.flags &= ~HWC_FLUSH;
  560. }
  561. static int 
  562. write_event_data_2 (u32 ext_int_param)
  563. {
  564. write_hwcb_t *hwcb;
  565. int retval = 0;
  566. #ifdef DUMP_HWC_WRITE_ERROR
  567. if ((ext_int_param & HWC_EXT_INT_PARAM_ADDR)
  568.     != (unsigned long) hwc_data.current_hwcb) {
  569. internal_print (
  570.        DELAYED_WRITE,
  571.        HWC_RW_PRINT_HEADER
  572.        "write_event_data_2 : "
  573.        "HWCB address does not fit "
  574.        "(expected: 0x%lx, got: 0x%lx).n",
  575.        (unsigned long) hwc_data.current_hwcb,
  576.        ext_int_param);
  577. return -EINVAL;
  578. }
  579. #endif
  580. hwcb = (write_hwcb_t *) OUT_HWCB;
  581. #ifdef DUMP_HWC_WRITE_LIST_ERROR
  582. if (((unsigned char *) hwcb) != hwc_data.current_hwcb) {
  583. __asm__ ("LHI 1,0xe22nt"
  584.  "LRA 2,0(%0)nt"
  585.  "LRA 3,0(%1)nt"
  586.  "LRA 4,0(%2)nt"
  587.  "LRA 5,0(%3)nt"
  588.  "J .+0 nt"
  589.       :
  590.       :  "a" (OUT_HWCB),
  591.  "a" (hwc_data.current_hwcb),
  592.  "a" (BUF_HWCB),
  593.  "a" (hwcb)
  594.       :  "1", "2", "3", "4", "5");
  595. }
  596. #endif
  597. #ifdef DUMP_HWC_WRITE_ERROR
  598. if (hwcb->response_code != 0x0020) {
  599. __asm__ ("LHI 1,0xe21nt"
  600.  "LRA 2,0(%0)nt"
  601.  "LRA 3,0(%1)nt"
  602.  "LRA 4,0(%2)nt"
  603.  "LH 5,0(%3)nt"
  604.  "SRL 5,8nt"
  605.  "J .+0 nt"
  606.       :
  607.       :  "a" (OUT_HWCB), "a" (hwc_data.current_hwcb),
  608.  "a" (BUF_HWCB),
  609.  "a" (&(hwc_data.hwcb_count))
  610.       :  "1", "2", "3", "4", "5");
  611. }
  612. #endif
  613. switch (hwcb->response_code) {
  614. case 0x0020:
  615. retval = OUT_HWCB_CHAR;
  616. release_write_hwcb ();
  617. break;
  618. case 0x0040:
  619. case 0x0340:
  620. case 0x40F0:
  621. if (!hwc_data.read_statechange) {
  622. hwcb->response_code = 0;
  623. start_poll_hwc ();
  624. }
  625. retval = -EIO;
  626. break;
  627. default:
  628. internal_print (
  629.        DELAYED_WRITE,
  630.        HWC_RW_PRINT_HEADER
  631.        "write_event_data_2 : "
  632.        "failed operation "
  633.        "(response code: 0x%x "
  634.        "HWCB address: 0x%x).n",
  635.        hwcb->response_code,
  636.        hwcb);
  637. retval = -EIO;
  638. }
  639. if (retval == -EIO) {
  640. hwcb->control_mask[0] = 0;
  641. hwcb->control_mask[1] = 0;
  642. hwcb->control_mask[2] = 0;
  643. hwcb->response_code = 0;
  644. }
  645. hwc_data.current_servc = 0;
  646. hwc_data.current_hwcb = NULL;
  647. if (hwc_data.flags & HWC_FLUSH)
  648. flush_hwcbs ();
  649. return retval;
  650. }
  651. static void 
  652. do_put_line (
  653.     unsigned char *message,
  654.     unsigned short count)
  655. {
  656. if (add_mto (message, count) != count) {
  657. if (allocate_write_hwcb () < 0)
  658. reuse_write_hwcb ();
  659. #ifdef DUMP_HWC_WRITE_LIST_ERROR
  660. if (add_mto (message, count) != count)
  661. __asm__ ("LHI 1,0xe32nt"
  662.  "LRA 2,0(%0)nt"
  663.  "L 3,0(%1)nt"
  664.  "LRA 4,0(%2)nt"
  665.  "LRA 5,0(%3)nt"
  666.  "J .+0 nt"
  667.       :
  668.       :  "a" (message), "a" (&hwc_data.kmem_pages),
  669.  "a" (BUF_HWCB), "a" (OUT_HWCB)
  670.       :  "1", "2", "3", "4", "5");
  671. #else
  672. add_mto (message, count);
  673. #endif
  674. }
  675. }
  676. static void 
  677. put_line (
  678.  unsigned char *message,
  679.  unsigned short count)
  680. {
  681. if ((!hwc_data.obuf_start) && (hwc_data.flags & HWC_WTIMER_RUNS)) {
  682. del_timer (&hwc_data.write_timer);
  683. hwc_data.flags &= ~HWC_WTIMER_RUNS;
  684. }
  685. hwc_data.obuf_start += count;
  686. do_put_line (message, count);
  687. hwc_data.obuf_start -= count;
  688. }
  689. static void 
  690. set_alarm (void)
  691. {
  692. write_hwcb_t *hwcb;
  693. if ((!BUF_HWCB) || (BUF_HWCB == hwc_data.current_hwcb))
  694. allocate_write_hwcb ();
  695. hwcb = (write_hwcb_t *) BUF_HWCB;
  696. hwcb->msgbuf.mdb.mdb_body.go.general_msg_flags |= GMF_SndAlrm;
  697. }
  698. static void 
  699. hwc_write_timeout (unsigned long data)
  700. {
  701. unsigned long flags;
  702. spin_lock_irqsave (&hwc_data.lock, flags);
  703. hwc_data.obuf_start = hwc_data.obuf_count;
  704. if (hwc_data.obuf_count)
  705. put_line (hwc_data.obuf, hwc_data.obuf_count);
  706. hwc_data.obuf_start = 0;
  707. hwc_data.obuf_cursor = 0;
  708. hwc_data.obuf_count = 0;
  709. write_event_data_1 ();
  710. spin_unlock_irqrestore (&hwc_data.lock, flags);
  711. }
  712. static int 
  713. do_hwc_write (
  714.      int from_user,
  715.      unsigned char *msg,
  716.      unsigned int count,
  717.      unsigned char write_time)
  718. {
  719. unsigned int i_msg = 0;
  720. unsigned short int spaces = 0;
  721. unsigned int processed_characters = 0;
  722. unsigned char ch;
  723. unsigned short int obuf_count;
  724. unsigned short int obuf_cursor;
  725. unsigned short int obuf_columns;
  726. if (hwc_data.obuf_start) {
  727. obuf_cursor = 0;
  728. obuf_count = 0;
  729. obuf_columns = MIN (hwc_data.ioctls.columns,
  730.     MAX_MESSAGE_SIZE - hwc_data.obuf_start);
  731. } else {
  732. obuf_cursor = hwc_data.obuf_cursor;
  733. obuf_count = hwc_data.obuf_count;
  734. obuf_columns = hwc_data.ioctls.columns;
  735. }
  736. for (i_msg = 0; i_msg < count; i_msg++) {
  737. if (from_user)
  738. get_user (ch, msg + i_msg);
  739. else
  740. ch = msg[i_msg];
  741. processed_characters++;
  742. if ((obuf_cursor == obuf_columns) &&
  743.     (ch != 'n') &&
  744.     (ch != 't')) {
  745. put_line (&hwc_data.obuf[hwc_data.obuf_start],
  746.   obuf_columns);
  747. obuf_cursor = 0;
  748. obuf_count = 0;
  749. }
  750. switch (ch) {
  751. case 'n':
  752. put_line (&hwc_data.obuf[hwc_data.obuf_start],
  753.   obuf_count);
  754. obuf_cursor = 0;
  755. obuf_count = 0;
  756. break;
  757. case 'a':
  758. hwc_data.obuf_start += obuf_count;
  759. set_alarm ();
  760. hwc_data.obuf_start -= obuf_count;
  761. break;
  762. case 't':
  763. do {
  764. if (obuf_cursor < obuf_columns) {
  765. hwc_data.obuf[hwc_data.obuf_start +
  766.       obuf_cursor]
  767.     = HWC_ASCEBC (' ');
  768. obuf_cursor++;
  769. } else
  770. break;
  771. } while (obuf_cursor % hwc_data.ioctls.width_htab);
  772. break;
  773. case 'f':
  774. case 'v':
  775. spaces = obuf_cursor;
  776. put_line (&hwc_data.obuf[hwc_data.obuf_start],
  777.   obuf_count);
  778. obuf_count = obuf_cursor;
  779. while (spaces) {
  780. hwc_data.obuf[hwc_data.obuf_start +
  781.       obuf_cursor - spaces]
  782.     = HWC_ASCEBC (' ');
  783. spaces--;
  784. }
  785. break;
  786. case 'b':
  787. if (obuf_cursor)
  788. obuf_cursor--;
  789. break;
  790. case 'r':
  791. obuf_cursor = 0;
  792. break;
  793. case 0x00:
  794. put_line (&hwc_data.obuf[hwc_data.obuf_start],
  795.   obuf_count);
  796. obuf_cursor = 0;
  797. obuf_count = 0;
  798. goto out;
  799. default:
  800. if (isprint (ch))
  801. hwc_data.obuf[hwc_data.obuf_start +
  802.       obuf_cursor++]
  803.     = HWC_ASCEBC (ch);
  804. }
  805. if (obuf_cursor > obuf_count)
  806. obuf_count = obuf_cursor;
  807. }
  808. if (obuf_cursor) {
  809. if (hwc_data.obuf_start ||
  810.     (hwc_data.ioctls.final_nl == 0)) {
  811. put_line (&hwc_data.obuf[hwc_data.obuf_start],
  812.   obuf_count);
  813. obuf_cursor = 0;
  814. obuf_count = 0;
  815. } else {
  816. if (hwc_data.ioctls.final_nl > 0) {
  817. if (hwc_data.flags & HWC_WTIMER_RUNS) {
  818. mod_timer (&hwc_data.write_timer,
  819.    jiffies + hwc_data.ioctls.final_nl * HZ / 10);
  820. } else {
  821. init_timer (&hwc_data.write_timer);
  822. hwc_data.write_timer.function =
  823.     hwc_write_timeout;
  824. hwc_data.write_timer.data =
  825.     (unsigned long) NULL;
  826. hwc_data.write_timer.expires =
  827.     jiffies +
  828.     hwc_data.ioctls.final_nl * HZ / 10;
  829. add_timer (&hwc_data.write_timer);
  830. hwc_data.flags |= HWC_WTIMER_RUNS;
  831. }
  832. } else;
  833. }
  834. } else;
  835.       out:
  836. if (!hwc_data.obuf_start) {
  837. hwc_data.obuf_cursor = obuf_cursor;
  838. hwc_data.obuf_count = obuf_count;
  839. }
  840. if (write_time == IMMEDIATE_WRITE)
  841. write_event_data_1 ();
  842. return processed_characters;
  843. }
  844. signed int 
  845. hwc_write (int from_user, const unsigned char *msg, unsigned int count)
  846. {
  847. unsigned long flags;
  848. int retval;
  849. spin_lock_irqsave (&hwc_data.lock, flags);
  850. retval = do_hwc_write (from_user, (unsigned char *) msg,
  851.        count, IMMEDIATE_WRITE);
  852. spin_unlock_irqrestore (&hwc_data.lock, flags);
  853. return retval;
  854. }
  855. unsigned int 
  856. hwc_chars_in_buffer (unsigned char flag)
  857. {
  858. unsigned short int number = 0;
  859. unsigned long flags;
  860. spin_lock_irqsave (&hwc_data.lock, flags);
  861. if (flag & IN_HWCB)
  862. number += ALL_HWCB_CHAR;
  863. if (flag & IN_WRITE_BUF)
  864. number += hwc_data.obuf_cursor;
  865. spin_unlock_irqrestore (&hwc_data.lock, flags);
  866. return number;
  867. }
  868. static inline int 
  869. nr_setbits (kmem_pages_t arg)
  870. {
  871. int i;
  872. int nr = 0;
  873. for (i = 0; i < (sizeof (arg) << 3); i++) {
  874. if (arg & 1)
  875. nr++;
  876. arg >>= 1;
  877. }
  878. return nr;
  879. }
  880. unsigned int 
  881. hwc_write_room (unsigned char flag)
  882. {
  883. unsigned int number = 0;
  884. unsigned long flags;
  885. write_hwcb_t *hwcb;
  886. spin_lock_irqsave (&hwc_data.lock, flags);
  887. if (flag & IN_HWCB) {
  888. if (BUF_HWCB) {
  889. hwcb = (write_hwcb_t *) BUF_HWCB;
  890. number += MAX_HWCB_ROOM - hwcb->length;
  891. }
  892. number += (hwc_data.ioctls.kmem_hwcb -
  893.    nr_setbits (hwc_data.kmem_pages)) *
  894.     (MAX_HWCB_ROOM -
  895.      (sizeof (write_hwcb_t) + sizeof (mto_t)));
  896. }
  897. if (flag & IN_WRITE_BUF)
  898. number += MAX_HWCB_ROOM - hwc_data.obuf_cursor;
  899. spin_unlock_irqrestore (&hwc_data.lock, flags);
  900. return number;
  901. }
  902. void 
  903. hwc_flush_buffer (unsigned char flag)
  904. {
  905. unsigned long flags;
  906. spin_lock_irqsave (&hwc_data.lock, flags);
  907. if (flag & IN_HWCB) {
  908. if (hwc_data.current_servc != HWC_CMDW_WRITEDATA)
  909. flush_hwcbs ();
  910. else
  911. hwc_data.flags |= HWC_FLUSH;
  912. }
  913. if (flag & IN_WRITE_BUF) {
  914. hwc_data.obuf_cursor = 0;
  915. hwc_data.obuf_count = 0;
  916. }
  917. spin_unlock_irqrestore (&hwc_data.lock, flags);
  918. }
  919. unsigned short int 
  920. seperate_cases (unsigned char *buf, unsigned short int count)
  921. {
  922. unsigned short int i_in;
  923. unsigned short int i_out = 0;
  924. unsigned char _case = 0;
  925. for (i_in = 0; i_in < count; i_in++) {
  926. if (buf[i_in] == hwc_data.ioctls.delim) {
  927. if ((i_in + 1 < count) &&
  928.     (buf[i_in + 1] == hwc_data.ioctls.delim)) {
  929. buf[i_out] = hwc_data.ioctls.delim;
  930. i_out++;
  931. i_in++;
  932. } else
  933. _case = ~_case;
  934. } else {
  935. if (_case) {
  936. if (hwc_data.ioctls.tolower)
  937. buf[i_out] = _ebc_toupper[buf[i_in]];
  938. else
  939. buf[i_out] = _ebc_tolower[buf[i_in]];
  940. } else
  941. buf[i_out] = buf[i_in];
  942. i_out++;
  943. }
  944. }
  945. return i_out;
  946. }
  947. #ifdef DUMP_HWCB_INPUT
  948. static int 
  949. gds_vector_name (u16 id, unsigned char name[])
  950. {
  951. int retval = 0;
  952. switch (id) {
  953. case GDS_ID_MDSMU:
  954. name = "Multiple Domain Support Message Unit";
  955. break;
  956. case GDS_ID_MDSRouteInfo:
  957. name = "MDS Routing Information";
  958. break;
  959. case GDS_ID_AgUnWrkCorr:
  960. name = "Agent Unit of Work Correlator";
  961. break;
  962. case GDS_ID_SNACondReport:
  963. name = "SNA Condition Report";
  964. break;
  965. case GDS_ID_CPMSU:
  966. name = "CP Management Services Unit";
  967. break;
  968. case GDS_ID_RoutTargInstr:
  969. name = "Routing and Targeting Instructions";
  970. break;
  971. case GDS_ID_OpReq:
  972. name = "Operate Request";
  973. break;
  974. case GDS_ID_TextCmd:
  975. name = "Text Command";
  976. break;
  977. default:
  978. name = "unknown GDS variable";
  979. retval = -EINVAL;
  980. }
  981. return retval;
  982. }
  983. #endif
  984. inline static gds_vector_t *
  985. find_gds_vector (
  986. gds_vector_t * start, void *end, u16 id)
  987. {
  988. gds_vector_t *vec;
  989. gds_vector_t *retval = NULL;
  990. vec = start;
  991. while (((void *) vec) < end) {
  992. if (vec->gds_id == id) {
  993. #ifdef DUMP_HWCB_INPUT
  994. int retval_name;
  995. unsigned char name[64];
  996. retval_name = gds_vector_name (id, name);
  997. internal_print (
  998.        DELAYED_WRITE,
  999.        HWC_RW_PRINT_HEADER
  1000.   "%s at 0x%x up to 0x%x, length: %d",
  1001.        name,
  1002.        (unsigned long) vec,
  1003.       ((unsigned long) vec) + vec->length - 1,
  1004.        vec->length);
  1005. if (retval_name < 0)
  1006. internal_print (
  1007.        IMMEDIATE_WRITE,
  1008.        ", id: 0x%xn",
  1009.        vec->gds_id);
  1010. else
  1011. internal_print (
  1012.        IMMEDIATE_WRITE,
  1013.        "n");
  1014. #endif
  1015. retval = vec;
  1016. break;
  1017. }
  1018. vec = (gds_vector_t *) (((unsigned long) vec) + vec->length);
  1019. }
  1020. return retval;
  1021. }
  1022. inline static gds_subvector_t *
  1023. find_gds_subvector (
  1024.    gds_subvector_t * start, void *end, u8 key)
  1025. {
  1026. gds_subvector_t *subvec;
  1027. gds_subvector_t *retval = NULL;
  1028. subvec = start;
  1029. while (((void *) subvec) < end) {
  1030. if (subvec->key == key) {
  1031. retval = subvec;
  1032. break;
  1033. }
  1034. subvec = (gds_subvector_t *)
  1035.     (((unsigned long) subvec) + subvec->length);
  1036. }
  1037. return retval;
  1038. }
  1039. inline static int 
  1040. get_input (void *start, void *end)
  1041. {
  1042. int count;
  1043. count = ((unsigned long) end) - ((unsigned long) start);
  1044. if (hwc_data.ioctls.tolower)
  1045. EBC_TOLOWER (start, count);
  1046. if (hwc_data.ioctls.delim)
  1047. count = seperate_cases (start, count);
  1048. HWC_EBCASC_STR (start, count);
  1049. if (hwc_data.ioctls.echo)
  1050. do_hwc_write (0, start, count, IMMEDIATE_WRITE);
  1051. if (hwc_data.calls != NULL)
  1052. if (hwc_data.calls->move_input != NULL)
  1053. (hwc_data.calls->move_input) (start, count);
  1054. return count;
  1055. }
  1056. inline static int 
  1057. eval_selfdeftextmsg (gds_subvector_t * start, void *end)
  1058. {
  1059. gds_subvector_t *subvec;
  1060. void *subvec_data;
  1061. void *subvec_end;
  1062. int retval = 0;
  1063. subvec = start;
  1064. while (((void *) subvec) < end) {
  1065. subvec = find_gds_subvector (subvec, end, 0x30);
  1066. if (!subvec)
  1067. break;
  1068. subvec_data = (void *)
  1069.     (((unsigned long) subvec) +
  1070.      sizeof (gds_subvector_t));
  1071. subvec_end = (void *)
  1072.     (((unsigned long) subvec) + subvec->length);
  1073. retval += get_input (subvec_data, subvec_end);
  1074. subvec = (gds_subvector_t *) subvec_end;
  1075. }
  1076. return retval;
  1077. }
  1078. inline static int 
  1079. eval_textcmd (gds_subvector_t * start, void *end)
  1080. {
  1081. gds_subvector_t *subvec;
  1082. gds_subvector_t *subvec_data;
  1083. void *subvec_end;
  1084. int retval = 0;
  1085. subvec = start;
  1086. while (((void *) subvec) < end) {
  1087. subvec = find_gds_subvector (
  1088.  subvec, end, GDS_KEY_SelfDefTextMsg);
  1089. if (!subvec)
  1090. break;
  1091. subvec_data = (gds_subvector_t *)
  1092.     (((unsigned long) subvec) +
  1093.      sizeof (gds_subvector_t));
  1094. subvec_end = (void *)
  1095.     (((unsigned long) subvec) + subvec->length);
  1096. retval += eval_selfdeftextmsg (subvec_data, subvec_end);
  1097. subvec = (gds_subvector_t *) subvec_end;
  1098. }
  1099. return retval;
  1100. }
  1101. inline static int 
  1102. eval_cpmsu (gds_vector_t * start, void *end)
  1103. {
  1104. gds_vector_t *vec;
  1105. gds_subvector_t *vec_data;
  1106. void *vec_end;
  1107. int retval = 0;
  1108. vec = start;
  1109. while (((void *) vec) < end) {
  1110. vec = find_gds_vector (vec, end, GDS_ID_TextCmd);
  1111. if (!vec)
  1112. break;
  1113. vec_data = (gds_subvector_t *)
  1114.     (((unsigned long) vec) + sizeof (gds_vector_t));
  1115. vec_end = (void *) (((unsigned long) vec) + vec->length);
  1116. retval += eval_textcmd (vec_data, vec_end);
  1117. vec = (gds_vector_t *) vec_end;
  1118. }
  1119. return retval;
  1120. }
  1121. inline static int 
  1122. eval_mdsmu (gds_vector_t * start, void *end)
  1123. {
  1124. gds_vector_t *vec;
  1125. gds_vector_t *vec_data;
  1126. void *vec_end;
  1127. int retval = 0;
  1128. vec = find_gds_vector (start, end, GDS_ID_CPMSU);
  1129. if (vec) {
  1130. vec_data = (gds_vector_t *)
  1131.     (((unsigned long) vec) + sizeof (gds_vector_t));
  1132. vec_end = (void *) (((unsigned long) vec) + vec->length);
  1133. retval = eval_cpmsu (vec_data, vec_end);
  1134. }
  1135. return retval;
  1136. }
  1137. static int 
  1138. eval_evbuf (gds_vector_t * start, void *end)
  1139. {
  1140. gds_vector_t *vec;
  1141. gds_vector_t *vec_data;
  1142. void *vec_end;
  1143. int retval = 0;
  1144. vec = find_gds_vector (start, end, GDS_ID_MDSMU);
  1145. if (vec) {
  1146. vec_data = (gds_vector_t *)
  1147.     (((unsigned long) vec) + sizeof (gds_vector_t));
  1148. vec_end = (void *) (((unsigned long) vec) + vec->length);
  1149. retval = eval_mdsmu (vec_data, vec_end);
  1150. }
  1151. return retval;
  1152. }
  1153. static inline int 
  1154. eval_hwc_receive_mask (_hwcb_mask_t mask)
  1155. {
  1156. hwc_data.write_nonprio
  1157.     = ((mask & ET_Msg_Mask) == ET_Msg_Mask);
  1158. hwc_data.write_prio
  1159.     = ((mask & ET_PMsgCmd_Mask) == ET_PMsgCmd_Mask);
  1160. if (hwc_data.write_prio || hwc_data.write_nonprio) {
  1161. internal_print (
  1162.        DELAYED_WRITE,
  1163.        HWC_RW_PRINT_HEADER
  1164.        "can write messagesn");
  1165. return 0;
  1166. } else {
  1167. internal_print (
  1168.        DELAYED_WRITE,
  1169.        HWC_RW_PRINT_HEADER
  1170.        "can not write messagesn");
  1171. return -1;
  1172. }
  1173. }
  1174. static inline int 
  1175. eval_hwc_send_mask (_hwcb_mask_t mask)
  1176. {
  1177. hwc_data.read_statechange
  1178.     = ((mask & ET_StateChange_Mask) == ET_StateChange_Mask);
  1179. if (hwc_data.read_statechange)
  1180. internal_print (
  1181.        DELAYED_WRITE,
  1182.        HWC_RW_PRINT_HEADER
  1183.      "can read state change notificationsn");
  1184. else
  1185. internal_print (
  1186.        DELAYED_WRITE,
  1187.        HWC_RW_PRINT_HEADER
  1188.  "can not read state change notificationsn");
  1189. hwc_data.sig_quiesce
  1190.     = ((mask & ET_SigQuiesce_Mask) == ET_SigQuiesce_Mask);
  1191. if (hwc_data.sig_quiesce)
  1192. internal_print (
  1193.        DELAYED_WRITE,
  1194.        HWC_RW_PRINT_HEADER
  1195.        "can receive signal quiescen");
  1196. else
  1197. internal_print (
  1198.        DELAYED_WRITE,
  1199.        HWC_RW_PRINT_HEADER
  1200.        "can not receive signal quiescen");
  1201. hwc_data.read_nonprio
  1202.     = ((mask & ET_OpCmd_Mask) == ET_OpCmd_Mask);
  1203. if (hwc_data.read_nonprio)
  1204. internal_print (
  1205.        DELAYED_WRITE,
  1206.        HWC_RW_PRINT_HEADER
  1207.        "can read commandsn");
  1208. hwc_data.read_prio
  1209.     = ((mask & ET_PMsgCmd_Mask) == ET_PMsgCmd_Mask);
  1210. if (hwc_data.read_prio)
  1211. internal_print (
  1212.        DELAYED_WRITE,
  1213.        HWC_RW_PRINT_HEADER
  1214.        "can read priority commandsn");
  1215. if (hwc_data.read_prio || hwc_data.read_nonprio) {
  1216. return 0;
  1217. } else {
  1218. internal_print (
  1219.        DELAYED_WRITE,
  1220.        HWC_RW_PRINT_HEADER
  1221.      "can not read commands from operatorn");
  1222. return -1;
  1223. }
  1224. }
  1225. static int 
  1226. eval_statechangebuf (statechangebuf_t * scbuf)
  1227. {
  1228. int retval = 0;
  1229. internal_print (
  1230.        DELAYED_WRITE,
  1231.        HWC_RW_PRINT_HEADER
  1232.        "HWC state change detectedn");
  1233. if (scbuf->validity_hwc_active_facility_mask) {
  1234. }
  1235. if (scbuf->validity_hwc_receive_mask) {
  1236. if (scbuf->mask_length != 4) {
  1237. #ifdef DUMP_HWC_INIT_ERROR
  1238. __asm__ ("LHI 1,0xe50nt"
  1239.  "LRA 2,0(%0)nt"
  1240.  "J .+0 nt"
  1241.       :
  1242.       :  "a" (scbuf)
  1243.       :  "1", "2");
  1244. #endif
  1245. } else {
  1246. retval += eval_hwc_receive_mask
  1247.     (scbuf->hwc_receive_mask);
  1248. }
  1249. }
  1250. if (scbuf->validity_hwc_send_mask) {
  1251. if (scbuf->mask_length != 4) {
  1252. #ifdef DUMP_HWC_INIT_ERROR
  1253. __asm__ ("LHI 1,0xe51nt"
  1254.  "LRA 2,0(%0)nt"
  1255.  "J .+0 nt"
  1256.       :
  1257.       :  "a" (scbuf)
  1258.       :  "1", "2");
  1259. #endif
  1260. } else {
  1261. retval += eval_hwc_send_mask
  1262.     (scbuf->hwc_send_mask);
  1263. }
  1264. }
  1265. if (scbuf->validity_read_data_function_mask) {
  1266. }
  1267. return retval;
  1268. }
  1269. #ifdef CONFIG_SMP
  1270. extern unsigned long cpu_online_map;
  1271. static volatile unsigned long cpu_quiesce_map;
  1272. static void 
  1273. do_load_quiesce_psw (void)
  1274. {
  1275. psw_t quiesce_psw;
  1276. clear_bit (smp_processor_id (), &cpu_quiesce_map);
  1277. if (smp_processor_id () == 0) {
  1278. while (cpu_quiesce_map != 0) ;
  1279. quiesce_psw.mask = _DW_PSW_MASK;
  1280. quiesce_psw.addr = 0xfff;
  1281. __load_psw (quiesce_psw);
  1282. }
  1283. signal_processor (smp_processor_id (), sigp_stop);
  1284. }
  1285. static void 
  1286. do_machine_quiesce (void)
  1287. {
  1288. cpu_quiesce_map = cpu_online_map;
  1289. smp_call_function (do_load_quiesce_psw, NULL, 0, 0);
  1290. do_load_quiesce_psw ();
  1291. }
  1292. #else
  1293. static void 
  1294. do_machine_quiesce (void)
  1295. {
  1296. psw_t quiesce_psw;
  1297. quiesce_psw.mask = _DW_PSW_MASK;
  1298. queisce_psw.addr = 0xfff;
  1299. __load_psw (quiesce_psw);
  1300. }
  1301. #endif
  1302. static int 
  1303. process_evbufs (void *start, void *end)
  1304. {
  1305. int retval = 0;
  1306. evbuf_t *evbuf;
  1307. void *evbuf_end;
  1308. gds_vector_t *evbuf_data;
  1309. evbuf = (evbuf_t *) start;
  1310. while (((void *) evbuf) < end) {
  1311. evbuf_data = (gds_vector_t *)
  1312.     (((unsigned long) evbuf) + sizeof (evbuf_t));
  1313. evbuf_end = (void *) (((unsigned long) evbuf) + evbuf->length);
  1314. switch (evbuf->type) {
  1315. case ET_OpCmd:
  1316. case ET_CntlProgOpCmd:
  1317. case ET_PMsgCmd:
  1318. #ifdef DUMP_HWCB_INPUT
  1319. internal_print (
  1320.        DELAYED_WRITE,
  1321.        HWC_RW_PRINT_HEADER
  1322.        "event buffer "
  1323.    "at 0x%x up to 0x%x, length: %dn",
  1324.        (unsigned long) evbuf,
  1325.        (unsigned long) (evbuf_end - 1),
  1326.        evbuf->length);
  1327. dump_storage_area ((void *) evbuf, evbuf->length);
  1328. #endif
  1329. retval += eval_evbuf (evbuf_data, evbuf_end);
  1330. break;
  1331. case ET_StateChange:
  1332. retval += eval_statechangebuf
  1333.     ((statechangebuf_t *) evbuf);
  1334. break;
  1335. case ET_SigQuiesce:
  1336. _machine_restart = do_machine_quiesce;
  1337. _machine_halt = do_machine_quiesce;
  1338. _machine_power_off = do_machine_quiesce;
  1339. ctrl_alt_del ();
  1340. break;
  1341. default:
  1342. internal_print (
  1343.        DELAYED_WRITE,
  1344.        HWC_RW_PRINT_HEADER
  1345.        "unconditional read: "
  1346.        "unknown event buffer found, "
  1347.        "type 0x%x",
  1348.        evbuf->type);
  1349. retval = -ENOSYS;
  1350. }
  1351. evbuf = (evbuf_t *) evbuf_end;
  1352. }
  1353. return retval;
  1354. }
  1355. static int 
  1356. unconditional_read_1 (void)
  1357. {
  1358. unsigned short int condition_code;
  1359. read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;
  1360. int retval;
  1361. #if 0
  1362. if ((!hwc_data.read_prio) && (!hwc_data.read_nonprio))
  1363. return -EOPNOTSUPP;
  1364. if (hwc_data.current_servc)
  1365. return -EBUSY;
  1366. #endif
  1367. memset (hwcb, 0x00, PAGE_SIZE);
  1368. memcpy (hwcb, &read_hwcb_template, sizeof (read_hwcb_t));
  1369. condition_code = service_call (HWC_CMDW_READDATA, hwc_data.page);
  1370. #ifdef DUMP_HWC_READ_ERROR
  1371. if (condition_code == HWC_NOT_OPERATIONAL)
  1372. __asm__ ("LHI 1,0xe40nt"
  1373.  "L 2,0(%0)nt"
  1374.  "LRA 3,0(%1)nt"
  1375.  "J .+0 nt"
  1376.       :
  1377.       :  "a" (&condition_code), "a" (hwc_data.page)
  1378.       :  "1", "2", "3");
  1379. #endif
  1380. switch (condition_code) {
  1381. case HWC_COMMAND_INITIATED:
  1382. hwc_data.current_servc = HWC_CMDW_READDATA;
  1383. hwc_data.current_hwcb = hwc_data.page;
  1384. retval = condition_code;
  1385. break;
  1386. case HWC_BUSY:
  1387. retval = -EBUSY;
  1388. break;
  1389. default:
  1390. retval = -EIO;
  1391. }
  1392. return retval;
  1393. }
  1394. static int 
  1395. unconditional_read_2 (u32 ext_int_param)
  1396. {
  1397. read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page;
  1398. #ifdef DUMP_HWC_READ_ERROR
  1399. if ((hwcb->response_code != 0x0020) &&
  1400.     (hwcb->response_code != 0x0220) &&
  1401.     (hwcb->response_code != 0x60F0) &&
  1402.     (hwcb->response_code != 0x62F0))
  1403. __asm__ ("LHI 1,0xe41nt"
  1404.  "LRA 2,0(%0)nt"
  1405.  "L 3,0(%1)nt"
  1406.  "J .+0nt"
  1407.       :
  1408.       :  "a" (hwc_data.page), "a" (&(hwcb->response_code))
  1409.       :  "1", "2", "3");
  1410. #endif
  1411. hwc_data.current_servc = 0;
  1412. hwc_data.current_hwcb = NULL;
  1413. switch (hwcb->response_code) {
  1414. case 0x0020:
  1415. case 0x0220:
  1416. return process_evbufs (
  1417.      (void *) (((unsigned long) hwcb) + sizeof (read_hwcb_t)),
  1418.     (void *) (((unsigned long) hwcb) + hwcb->length));
  1419. case 0x60F0:
  1420. case 0x62F0:
  1421. internal_print (
  1422.        IMMEDIATE_WRITE,
  1423.        HWC_RW_PRINT_HEADER
  1424.        "unconditional read: "
  1425.      "got interrupt and tried to read input, "
  1426.   "but nothing found (response code=0x%x).n",
  1427.        hwcb->response_code);
  1428. return 0;
  1429. case 0x0100:
  1430. internal_print (
  1431.        IMMEDIATE_WRITE,
  1432.        HWC_RW_PRINT_HEADER
  1433.  "unconditional read: HWCB boundary violation - this "
  1434.  "must not occur in a correct driver, please contact "
  1435.        "authorn");
  1436. return -EIO;
  1437. case 0x0300:
  1438. internal_print (
  1439.        IMMEDIATE_WRITE,
  1440.        HWC_RW_PRINT_HEADER
  1441.        "unconditional read: "
  1442. "insufficient HWCB length - this must not occur in a "
  1443.    "correct driver, please contact authorn");
  1444. return -EIO;
  1445. case 0x01F0:
  1446. internal_print (
  1447.        IMMEDIATE_WRITE,
  1448.        HWC_RW_PRINT_HEADER
  1449.        "unconditional read: "
  1450.  "invalid command - this must not occur in a correct "
  1451.        "driver, please contact authorn");
  1452. return -EIO;
  1453. case 0x40F0:
  1454. internal_print (
  1455.        IMMEDIATE_WRITE,
  1456.        HWC_RW_PRINT_HEADER
  1457.        "unconditional read: invalid function coden");
  1458. return -EIO;
  1459. case 0x70F0:
  1460. internal_print (
  1461.        IMMEDIATE_WRITE,
  1462.        HWC_RW_PRINT_HEADER
  1463.       "unconditional read: invalid selection maskn");
  1464. return -EIO;
  1465. case 0x0040:
  1466. internal_print (
  1467.        IMMEDIATE_WRITE,
  1468.        HWC_RW_PRINT_HEADER
  1469.  "unconditional read: HWC equipment checkn");
  1470. return -EIO;
  1471. default:
  1472. internal_print (
  1473.        IMMEDIATE_WRITE,
  1474.        HWC_RW_PRINT_HEADER
  1475. "unconditional read: invalid response code %x - this "
  1476.  "must not occur in a correct driver, please contact "
  1477.        "authorn",
  1478.        hwcb->response_code);
  1479. return -EIO;
  1480. }
  1481. }
  1482. static int 
  1483. write_event_mask_1 (void)
  1484. {
  1485. unsigned int condition_code;
  1486. int retval;
  1487. condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page);
  1488. #ifdef DUMP_HWC_INIT_ERROR
  1489. if (condition_code == HWC_NOT_OPERATIONAL)
  1490. __asm__ ("LHI 1,0xe10nt"
  1491.  "L 2,0(%0)nt"
  1492.  "LRA 3,0(%1)nt"
  1493.  "J .+0nt"
  1494.       :
  1495.       :  "a" (&condition_code), "a" (hwc_data.page)
  1496.       :  "1", "2", "3");
  1497. #endif
  1498. switch (condition_code) {
  1499. case HWC_COMMAND_INITIATED:
  1500. hwc_data.current_servc = HWC_CMDW_WRITEMASK;
  1501. hwc_data.current_hwcb = hwc_data.page;
  1502. retval = condition_code;
  1503. break;
  1504. case HWC_BUSY:
  1505. retval = -EBUSY;
  1506. break;
  1507. default:
  1508. retval = -EIO;
  1509. }
  1510. return retval;
  1511. }
  1512. static int 
  1513. write_event_mask_2 (u32 ext_int_param)
  1514. {
  1515. init_hwcb_t *hwcb = (init_hwcb_t *) hwc_data.page;
  1516. int retval = 0;
  1517. if (hwcb->response_code != 0x0020) {
  1518. #ifdef DUMP_HWC_INIT_ERROR
  1519. __asm__ ("LHI 1,0xe11nt"
  1520.  "LRA 2,0(%0)nt"
  1521.  "L 3,0(%1)nt"
  1522.  "J .+0nt"
  1523.       :
  1524.       :  "a" (hwcb), "a" (&(hwcb->response_code))
  1525.       :  "1", "2", "3");
  1526. #else
  1527. retval = -1;
  1528. #endif
  1529. } else {
  1530. if (hwcb->mask_length != 4) {
  1531. #ifdef DUMP_HWC_INIT_ERROR
  1532. __asm__ ("LHI 1,0xe52nt"
  1533.  "LRA 2,0(%0)nt"
  1534.  "J .+0 nt"
  1535.       :
  1536.       :  "a" (hwcb)
  1537.       :  "1", "2");
  1538. #endif
  1539. } else {
  1540. retval += eval_hwc_receive_mask
  1541.     (hwcb->hwc_receive_mask);
  1542. retval += eval_hwc_send_mask (hwcb->hwc_send_mask);
  1543. }
  1544. }
  1545. hwc_data.current_servc = 0;
  1546. hwc_data.current_hwcb = NULL;
  1547. return retval;
  1548. }
  1549. static int 
  1550. set_hwc_ioctls (hwc_ioctls_t * ioctls, char correct)
  1551. {
  1552. int retval = 0;
  1553. hwc_ioctls_t tmp;
  1554. if (ioctls->width_htab > MAX_MESSAGE_SIZE) {
  1555. if (correct)
  1556. tmp.width_htab = MAX_MESSAGE_SIZE;
  1557. else
  1558. retval = -EINVAL;
  1559. } else
  1560. tmp.width_htab = ioctls->width_htab;
  1561. tmp.echo = ioctls->echo;
  1562. if (ioctls->columns > MAX_MESSAGE_SIZE) {
  1563. if (correct)
  1564. tmp.columns = MAX_MESSAGE_SIZE;
  1565. else
  1566. retval = -EINVAL;
  1567. } else
  1568. tmp.columns = ioctls->columns;
  1569. tmp.final_nl = ioctls->final_nl;
  1570. if (ioctls->max_hwcb < 2) {
  1571. if (correct)
  1572. tmp.max_hwcb = 2;
  1573. else
  1574. retval = -EINVAL;
  1575. } else
  1576. tmp.max_hwcb = ioctls->max_hwcb;
  1577. tmp.tolower = ioctls->tolower;
  1578. if (ioctls->kmem_hwcb > ioctls->max_hwcb) {
  1579. if (correct)
  1580. tmp.kmem_hwcb = ioctls->max_hwcb;
  1581. else
  1582. retval = -EINVAL;
  1583. } else
  1584. tmp.kmem_hwcb = ioctls->kmem_hwcb;
  1585. if (ioctls->kmem_hwcb > MAX_KMEM_PAGES) {
  1586. if (correct)
  1587. ioctls->kmem_hwcb = MAX_KMEM_PAGES;
  1588. else
  1589. retval = -EINVAL;
  1590. }
  1591. if (ioctls->kmem_hwcb < 2) {
  1592. if (correct)
  1593. ioctls->kmem_hwcb = 2;
  1594. else
  1595. retval = -EINVAL;
  1596. }
  1597. tmp.delim = ioctls->delim;
  1598. if (!(retval < 0))
  1599. hwc_data.ioctls = tmp;
  1600. return retval;
  1601. }
  1602. int 
  1603. do_hwc_init (void)
  1604. {
  1605. int retval;
  1606. memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t));
  1607. do {
  1608. retval = write_event_mask_1 ();
  1609. if (retval == -EBUSY) {
  1610. hwc_data.flags |= HWC_INIT;
  1611. __ctl_store (cr0, 0, 0);
  1612. cr0_save = cr0;
  1613. cr0 |= 0x00000200;
  1614. cr0 &= 0xFFFFF3AC;
  1615. __ctl_load (cr0, 0, 0);
  1616. asm volatile ("STOSM %0,0x01"
  1617.       :"=m" (psw_mask)::"memory");
  1618. while (!(hwc_data.flags & HWC_INTERRUPT))
  1619. barrier ();
  1620. asm volatile ("STNSM %0,0xFE"
  1621.       :"=m" (psw_mask)::"memory");
  1622. __ctl_load (cr0_save, 0, 0);
  1623. hwc_data.flags &= ~HWC_INIT;
  1624. }
  1625. } while (retval == -EBUSY);
  1626. if (retval == -EIO) {
  1627. hwc_data.flags |= HWC_BROKEN;
  1628. printk (HWC_RW_PRINT_HEADER "HWC not operationaln");
  1629. }
  1630. return retval;
  1631. }
  1632. void hwc_interrupt_handler (struct pt_regs *regs, __u16 code);
  1633. int 
  1634. hwc_init (void)
  1635. {
  1636. int retval;
  1637. #ifdef BUFFER_STRESS_TEST
  1638. init_hwcb_t *hwcb;
  1639. int i;
  1640. #endif
  1641. if (register_early_external_interrupt (0x2401, hwc_interrupt_handler,
  1642.        &ext_int_info_hwc) != 0)
  1643. panic ("Couldn't request external interrupts 0x2401");
  1644. spin_lock_init (&hwc_data.lock);
  1645. #ifdef USE_VM_DETECTION
  1646. if (MACHINE_IS_VM) {
  1647. if (hwc_data.init_ioctls.columns > 76)
  1648. hwc_data.init_ioctls.columns = 76;
  1649. hwc_data.init_ioctls.tolower = 1;
  1650. if (!hwc_data.init_ioctls.delim)
  1651. hwc_data.init_ioctls.delim = DEFAULT_CASE_DELIMITER;
  1652. } else {
  1653. hwc_data.init_ioctls.tolower = 0;
  1654. hwc_data.init_ioctls.delim = 0;
  1655. }
  1656. #endif
  1657. retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1);
  1658. hwc_data.kmem_start = (unsigned long)
  1659.     alloc_bootmem_low_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);
  1660. hwc_data.kmem_end = hwc_data.kmem_start +
  1661.     hwc_data.ioctls.kmem_hwcb * PAGE_SIZE - 1;
  1662. retval = do_hwc_init ();
  1663. ctl_set_bit (0, 9);
  1664. #ifdef BUFFER_STRESS_TEST
  1665. internal_print (
  1666.        DELAYED_WRITE,
  1667.        HWC_RW_PRINT_HEADER
  1668.        "use %i bytes for buffering.n",
  1669.        hwc_data.ioctls.kmem_hwcb * PAGE_SIZE);
  1670. for (i = 0; i < 500; i++) {
  1671. hwcb = (init_hwcb_t *) BUF_HWCB;
  1672. internal_print (
  1673.        DELAYED_WRITE,
  1674.        HWC_RW_PRINT_HEADER
  1675.   "This is stress test message #%i, free: %i bytesn",
  1676.        i,
  1677.      MAX_HWCB_ROOM - (hwcb->length + sizeof (mto_t)));
  1678. }
  1679. #endif
  1680. return /*retval */ 0;
  1681. }
  1682. signed int 
  1683. hwc_register_calls (hwc_high_level_calls_t * calls)
  1684. {
  1685. if (calls == NULL)
  1686. return -EINVAL;
  1687. if (hwc_data.calls != NULL)
  1688. return -EBUSY;
  1689. hwc_data.calls = calls;
  1690. return 0;
  1691. }
  1692. signed int 
  1693. hwc_unregister_calls (hwc_high_level_calls_t * calls)
  1694. {
  1695. if (hwc_data.calls == NULL)
  1696. return -EINVAL;
  1697. if (calls != hwc_data.calls)
  1698. return -EINVAL;
  1699. hwc_data.calls = NULL;
  1700. return 0;
  1701. }
  1702. int 
  1703. hwc_send (hwc_request_t * req)
  1704. {
  1705. unsigned long flags;
  1706. int retval;
  1707. int cc;
  1708. spin_lock_irqsave (&hwc_data.lock, flags);
  1709. if (!req || !req->callback || !req->block) {
  1710. retval = -EINVAL;
  1711. goto unlock;
  1712. }
  1713. if (hwc_data.request) {
  1714. retval = -ENOTSUPP;
  1715. goto unlock;
  1716. }
  1717. cc = service_call (req->word, req->block);
  1718. switch (cc) {
  1719. case 0:
  1720. hwc_data.request = req;
  1721. hwc_data.current_servc = req->word;
  1722. hwc_data.current_hwcb = req->block;
  1723. retval = 0;
  1724. break;
  1725. case 2:
  1726. retval = -EBUSY;
  1727. break;
  1728. default:
  1729. retval = -ENOSYS;
  1730. }
  1731.       unlock:
  1732. spin_unlock_irqrestore (&hwc_data.lock, flags);
  1733. return retval;
  1734. }
  1735. EXPORT_SYMBOL (hwc_send);
  1736. void 
  1737. do_hwc_callback (u32 ext_int_param)
  1738. {
  1739. if (!hwc_data.request || !hwc_data.request->callback)
  1740. return;
  1741. if ((ext_int_param & HWC_EXT_INT_PARAM_ADDR)
  1742.     != (unsigned long) hwc_data.request->block)
  1743. return;
  1744. hwc_data.request->callback (hwc_data.request);
  1745. hwc_data.request = NULL;
  1746. hwc_data.current_hwcb = NULL;
  1747. hwc_data.current_servc = 0;
  1748. }
  1749. void 
  1750. hwc_do_interrupt (u32 ext_int_param)
  1751. {
  1752. u32 finished_hwcb = ext_int_param & HWC_EXT_INT_PARAM_ADDR;
  1753. u32 evbuf_pending = ext_int_param & HWC_EXT_INT_PARAM_PEND;
  1754. if (hwc_data.flags & HWC_PTIMER_RUNS) {
  1755. del_timer (&hwc_data.poll_timer);
  1756. hwc_data.flags &= ~HWC_PTIMER_RUNS;
  1757. }
  1758. if (finished_hwcb) {
  1759. if ((unsigned long) hwc_data.current_hwcb != finished_hwcb) {
  1760. internal_print (
  1761.        DELAYED_WRITE,
  1762.        HWC_RW_PRINT_HEADER
  1763.        "interrupt: mismatch: "
  1764.        "ext. int param. (0x%x) vs. "
  1765.        "current HWCB (0x%x)n",
  1766.        ext_int_param,
  1767.        hwc_data.current_hwcb);
  1768. } else {
  1769. if (hwc_data.request) {
  1770. do_hwc_callback (ext_int_param);
  1771. } else {
  1772. switch (hwc_data.current_servc) {
  1773. case HWC_CMDW_WRITEMASK:
  1774. write_event_mask_2 (ext_int_param);
  1775. break;
  1776. case HWC_CMDW_WRITEDATA:
  1777. write_event_data_2 (ext_int_param);
  1778. break;
  1779. case HWC_CMDW_READDATA:
  1780. unconditional_read_2 (ext_int_param);
  1781. break;
  1782. default:
  1783. }
  1784. }
  1785. }
  1786. } else {
  1787. if (hwc_data.current_hwcb) {
  1788. internal_print (
  1789.        DELAYED_WRITE,
  1790.        HWC_RW_PRINT_HEADER
  1791.        "interrupt: mismatch: "
  1792.        "ext. int. param. (0x%x) vs. "
  1793.        "current HWCB (0x%x)n",
  1794.        ext_int_param,
  1795.        hwc_data.current_hwcb);
  1796. }
  1797. }
  1798. if (evbuf_pending) {
  1799. unconditional_read_1 ();
  1800. } else {
  1801. write_event_data_1 ();
  1802. }
  1803. if (!hwc_data.calls || !hwc_data.calls->wake_up)
  1804. return;
  1805. (hwc_data.calls->wake_up) ();
  1806. }
  1807. void 
  1808. hwc_interrupt_handler (struct pt_regs *regs, __u16 code)
  1809. {
  1810. int cpu = smp_processor_id ();
  1811. u32 ext_int_param = hwc_ext_int_param ();
  1812. irq_enter (cpu, 0x2401);
  1813. if (hwc_data.flags & HWC_INIT) {
  1814. hwc_data.flags |= HWC_INTERRUPT;
  1815. } else if (hwc_data.flags & HWC_BROKEN) {
  1816. if (!do_hwc_init ()) {
  1817. hwc_data.flags &= ~HWC_BROKEN;
  1818. internal_print (DELAYED_WRITE,
  1819. HWC_RW_PRINT_HEADER
  1820. "delayed HWC setup after"
  1821. " temporary breakdown"
  1822. " (ext. int. parameter=0x%x)n",
  1823. ext_int_param);
  1824. }
  1825. } else {
  1826. spin_lock (&hwc_data.lock);
  1827. hwc_do_interrupt (ext_int_param);
  1828. spin_unlock (&hwc_data.lock);
  1829. }
  1830. irq_exit (cpu, 0x2401);
  1831. }
  1832. void 
  1833. hwc_unblank (void)
  1834. {
  1835. spin_lock (&hwc_data.lock);
  1836. spin_unlock (&hwc_data.lock);
  1837. __ctl_store (cr0, 0, 0);
  1838. cr0_save = cr0;
  1839. cr0 |= 0x00000200;
  1840. cr0 &= 0xFFFFF3AC;
  1841. __ctl_load (cr0, 0, 0);
  1842. asm volatile ("STOSM %0,0x01":"=m" (psw_mask)::"memory");
  1843. while (ALL_HWCB_CHAR)
  1844. barrier ();
  1845. asm volatile ("STNSM %0,0xFE":"=m" (psw_mask)::"memory");
  1846. __ctl_load (cr0_save, 0, 0);
  1847. }
  1848. int 
  1849. hwc_ioctl (unsigned int cmd, unsigned long arg)
  1850. {
  1851. hwc_ioctls_t tmp = hwc_data.ioctls;
  1852. int retval = 0;
  1853. unsigned long flags;
  1854. unsigned int obuf;
  1855. spin_lock_irqsave (&hwc_data.lock, flags);
  1856. switch (cmd) {
  1857. case TIOCHWCSHTAB:
  1858. if (get_user (tmp.width_htab, (ioctl_htab_t *) arg))
  1859. goto fault;
  1860. break;
  1861. case TIOCHWCSECHO:
  1862. if (get_user (tmp.echo, (ioctl_echo_t *) arg))
  1863. goto fault;
  1864. break;
  1865. case TIOCHWCSCOLS:
  1866. if (get_user (tmp.columns, (ioctl_cols_t *) arg))
  1867. goto fault;
  1868. break;
  1869. case TIOCHWCSNL:
  1870. if (get_user (tmp.final_nl, (ioctl_nl_t *) arg))
  1871. goto fault;
  1872. break;
  1873. case TIOCHWCSOBUF:
  1874. if (get_user (obuf, (unsigned int *) arg))
  1875. goto fault;
  1876. if (obuf & 0xFFF)
  1877. tmp.max_hwcb = (((obuf | 0xFFF) + 1) >> 12);
  1878. else
  1879. tmp.max_hwcb = (obuf >> 12);
  1880. break;
  1881. case TIOCHWCSCASE:
  1882. if (get_user (tmp.tolower, (ioctl_case_t *) arg))
  1883. goto fault;
  1884. break;
  1885. case TIOCHWCSDELIM:
  1886. if (get_user (tmp.delim, (ioctl_delim_t *) arg))
  1887. goto fault;
  1888. break;
  1889. case TIOCHWCSINIT:
  1890. retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1);
  1891. break;
  1892. case TIOCHWCGHTAB:
  1893. if (put_user (tmp.width_htab, (ioctl_htab_t *) arg))
  1894. goto fault;
  1895. break;
  1896. case TIOCHWCGECHO:
  1897. if (put_user (tmp.echo, (ioctl_echo_t *) arg))
  1898. goto fault;
  1899. break;
  1900. case TIOCHWCGCOLS:
  1901. if (put_user (tmp.columns, (ioctl_cols_t *) arg))
  1902. goto fault;
  1903. break;
  1904. case TIOCHWCGNL:
  1905. if (put_user (tmp.final_nl, (ioctl_nl_t *) arg))
  1906. goto fault;
  1907. break;
  1908. case TIOCHWCGOBUF:
  1909. if (put_user (tmp.max_hwcb, (ioctl_obuf_t *) arg))
  1910. goto fault;
  1911. break;
  1912. case TIOCHWCGKBUF:
  1913. if (put_user (tmp.kmem_hwcb, (ioctl_obuf_t *) arg))
  1914. goto fault;
  1915. break;
  1916. case TIOCHWCGCASE:
  1917. if (put_user (tmp.tolower, (ioctl_case_t *) arg))
  1918. goto fault;
  1919. break;
  1920. case TIOCHWCGDELIM:
  1921. if (put_user (tmp.delim, (ioctl_delim_t *) arg))
  1922. goto fault;
  1923. break;
  1924. #if 0
  1925. case TIOCHWCGINIT:
  1926. if (put_user (&hwc_data.init_ioctls, (hwc_ioctls_t *) arg))
  1927. goto fault;
  1928. break;
  1929. case TIOCHWCGCURR:
  1930. if (put_user (&hwc_data.ioctls, (hwc_ioctls_t *) arg))
  1931. goto fault;
  1932. break;
  1933. #endif
  1934. default:
  1935. goto noioctlcmd;
  1936. }
  1937. if (_IOC_DIR (cmd) == _IOC_WRITE)
  1938. retval = set_hwc_ioctls (&tmp, 0);
  1939. goto out;
  1940.       fault:
  1941. retval = -EFAULT;
  1942. goto out;
  1943.       noioctlcmd:
  1944. retval = -ENOIOCTLCMD;
  1945.       out:
  1946. spin_unlock_irqrestore (&hwc_data.lock, flags);
  1947. return retval;
  1948. }