Locore.c revision 1.1.12.1 1 /* $NetBSD: Locore.c,v 1.1.12.1 2002/06/20 03:41:16 nathanw Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996 Wolfgang Solfrank.
5 * Copyright (C) 1995, 1996 TooLs GmbH.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by TooLs GmbH.
19 * 4. The name of TooLs GmbH may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <lib/libsa/stand.h>
35 #include "openfirm.h"
36
37 #include <machine/cpu.h>
38
39 vaddr_t OF_claim_virt __P((vaddr_t vaddr, int len));
40 vaddr_t OF_alloc_virt __P((int len, int align));
41 int OF_free_virt __P((vaddr_t vaddr, int len));
42 int OF_unmap_virt __P((vaddr_t vaddr, int len));
43 vaddr_t OF_map_phys __P((paddr_t paddr, off_t size, vaddr_t vaddr, int mode));
44 paddr_t OF_alloc_phys __P((int len, int align));
45 paddr_t OF_claim_phys __P((paddr_t phys, int len));
46 int OF_free_phys __P((paddr_t paddr, int len));
47
48 extern int openfirmware(void *);
49
50 void setup __P((void));
51
52 #if 0
53 #ifdef XCOFF_GLUE
54 asm (".text; .globl _entry; _entry: .long _start,0,0");
55 #endif
56
57 __dead void
58 _start(vpd, res, openfirm, arg, argl)
59 void *vpd;
60 int res;
61 int (*openfirm)(void *);
62 char *arg;
63 int argl;
64 {
65 extern char etext[];
66
67 #ifdef FIRMWORKSBUGS
68 syncicache((void *)RELOC, etext - (char *)RELOC);
69 #endif
70 openfirmware = openfirm; /* Save entry to Open Firmware */
71 setup();
72 main(arg, argl);
73 exit(0);
74 }
75 #endif
76
77 __dead void
78 _rtt()
79 {
80 struct {
81 cell_t name;
82 cell_t nargs;
83 cell_t nreturns;
84 } args;
85
86 args.name = ADR2CELL("exit");
87 args.nargs = 0;
88 args.nreturns = 0;
89 openfirmware(&args);
90 while (1); /* just in case */
91 }
92
93 void
94 OF_enter()
95 {
96 struct {
97 cell_t name;
98 cell_t nargs;
99 cell_t nreturns;
100 } args;
101
102 args.name = ADR2CELL("enter");
103 args.nargs = 0;
104 args.nreturns = 0;
105 openfirmware(&args);
106 }
107
108 int
109 OF_finddevice(name)
110 char *name;
111 {
112 struct {
113 cell_t name;
114 cell_t nargs;
115 cell_t nreturns;
116 cell_t device;
117 cell_t phandle;
118 } args;
119
120 args.name = ADR2CELL("finddevice");
121 args.nargs = 1;
122 args.nreturns = 1;
123 args.device = ADR2CELL(name);
124 if (openfirmware(&args) == -1)
125 return -1;
126 return args.phandle;
127 }
128
129 int
130 OF_instance_to_package(ihandle)
131 int ihandle;
132 {
133 struct {
134 cell_t name;
135 cell_t nargs;
136 cell_t nreturns;
137 cell_t ihandle;
138 cell_t phandle;
139 } args;
140
141 args.name = ADR2CELL("instance-to-package");
142 args.nargs = 1;
143 args.nreturns = 1;
144 args.ihandle = HDL2CELL(ihandle);
145 if (openfirmware(&args) == -1)
146 return -1;
147 return args.phandle;
148 }
149
150 int
151 OF_getprop(handle, prop, buf, buflen)
152 int handle;
153 char *prop;
154 void *buf;
155 int buflen;
156 {
157 struct {
158 cell_t name;
159 cell_t nargs;
160 cell_t nreturns;
161 cell_t phandle;
162 cell_t prop;
163 cell_t buf;
164 cell_t buflen;
165 cell_t size;
166 } args;
167
168 args.name = ADR2CELL("getprop");
169 args.nargs = 4;
170 args.nreturns = 1;
171 args.phandle = HDL2CELL(handle);
172 args.prop = ADR2CELL(prop);
173 args.buf = ADR2CELL(buf);
174 args.buflen = buflen;
175 if (openfirmware(&args) == -1)
176 return -1;
177 return args.size;
178 }
179
180 #ifdef __notyet__ /* Has a bug on FirePower */
181 int
182 OF_setprop(handle, prop, buf, len)
183 u_int handle;
184 char *prop;
185 void *buf;
186 int len;
187 {
188 struct {
189 cell_t name;
190 cell_t nargs;
191 cell_t nreturns;
192 cell_t phandle;
193 cell_t prop;
194 cell_t buf;
195 cell_t len;
196 cell_t size;
197 } args;
198
199 args.name = ADR2CELL("setprop");
200 args.nargs = 4;
201 args.nreturns = 1;
202 args.phandle = HDL2CELL(handle);
203 args.prop = ADR2CELL(prop);
204 args.buf = ADR2CELL(buf);
205 args.len = len;
206 if (openfirmware(&args) == -1)
207 return -1;
208 return args.size;
209 }
210 #endif
211
212 int
213 OF_open(dname)
214 char *dname;
215 {
216 struct {
217 cell_t name;
218 cell_t nargs;
219 cell_t nreturns;
220 cell_t dname;
221 cell_t handle;
222 } args;
223
224 args.name = ADR2CELL("open");
225 args.nargs = 1;
226 args.nreturns = 1;
227 args.dname = ADR2CELL(dname);
228 if (openfirmware(&args) == -1 ||
229 args.handle == 0)
230 return -1;
231 return args.handle;
232 }
233
234 void
235 OF_close(handle)
236 int handle;
237 {
238 struct {
239 cell_t name;
240 cell_t nargs;
241 cell_t nreturns;
242 cell_t handle;
243 } args;
244
245 args.name = ADR2CELL("close");
246 args.nargs = 1;
247 args.nreturns = 1;
248 args.handle = HDL2CELL(handle);
249 openfirmware(&args);
250 }
251
252 int
253 OF_write(handle, addr, len)
254 int handle;
255 void *addr;
256 int len;
257 {
258 struct {
259 cell_t name;
260 cell_t nargs;
261 cell_t nreturns;
262 cell_t ihandle;
263 cell_t addr;
264 cell_t len;
265 cell_t actual;
266 } args;
267
268 args.name = ADR2CELL("write");
269 args.nargs = 3;
270 args.nreturns = 1;
271 args.ihandle = HDL2CELL(handle);
272 args.addr = ADR2CELL(addr);
273 args.len = len;
274 if (openfirmware(&args) == -1)
275 return -1;
276 return args.actual;
277 }
278
279 int
280 OF_read(handle, addr, len)
281 int handle;
282 void *addr;
283 int len;
284 {
285 struct {
286 cell_t name;
287 cell_t nargs;
288 cell_t nreturns;
289 cell_t ihandle;
290 cell_t addr;
291 cell_t len;
292 cell_t actual;
293 } args;
294
295 args.name = ADR2CELL("read");
296 args.nargs = 3;
297 args.nreturns = 1;
298 args.ihandle = HDL2CELL(handle);
299 args.addr = ADR2CELL(addr);
300 args.len = len;
301 if (openfirmware(&args) == -1) {
302 return -1;
303 }
304 return args.actual;
305 }
306
307 int
308 OF_seek(handle, pos)
309 int handle;
310 u_quad_t pos;
311 {
312 struct {
313 cell_t name;
314 cell_t nargs;
315 cell_t nreturns;
316 cell_t handle;
317 cell_t poshi;
318 cell_t poslo;
319 cell_t status;
320 } args;
321
322 args.name = ADR2CELL("seek");
323 args.nargs = 3;
324 args.nreturns = 1;
325 args.handle = HDL2CELL(handle);
326 args.poshi = HDL2CELL(pos >> 32);
327 args.poslo = HDL2CELL(pos);
328 if (openfirmware(&args) == -1) {
329 return -1;
330 }
331 return args.status;
332 }
333
334 void
335 OF_release(virt, size)
336 void *virt;
337 u_int size;
338 {
339 struct {
340 cell_t name;
341 cell_t nargs;
342 cell_t nreturns;
343 cell_t virt;
344 cell_t size;
345 } args;
346
347 args.name = ADR2CELL("release");
348 args.nargs = 2;
349 args.nreturns = 0;
350 args.virt = ADR2CELL(virt);
351 args.size = size;
352 openfirmware(&args);
353 }
354
355 int
356 OF_milliseconds()
357 {
358 struct {
359 cell_t name;
360 cell_t nargs;
361 cell_t nreturns;
362 cell_t ms;
363 } args;
364
365 args.name = ADR2CELL("milliseconds");
366 args.nargs = 0;
367 args.nreturns = 1;
368 openfirmware(&args);
369 return args.ms;
370 }
371
372 void
373 OF_chain(virt, size, entry, arg, len)
374 void *virt;
375 u_int size;
376 void (*entry)();
377 void *arg;
378 u_int len;
379 {
380 extern int64_t romp;
381 extern int debug;
382 struct {
383 cell_t name;
384 cell_t nargs;
385 cell_t nreturns;
386 cell_t virt;
387 cell_t size;
388 cell_t entry;
389 cell_t arg;
390 cell_t len;
391 } args;
392
393 args.name = ADR2CELL("chain");
394 args.nargs = 5;
395 args.nreturns = 0;
396 args.virt = ADR2CELL(virt);
397 args.size = size;
398 args.entry = ADR2CELL(entry);
399 args.arg = ADR2CELL(arg);
400 args.len = len;
401 openfirmware(&args);
402 if (debug) {
403 printf("OF_chain: prom returned!\n");
404
405 /* OK, firmware failed us. Try calling prog directly */
406 printf("Calling entry(0, %p, %x, %lx, %lx)\n", arg, len,
407 (unsigned long)romp, (unsigned long)romp);
408 }
409 entry(0, arg, len, (unsigned long)romp, (unsigned long)romp);
410 panic("OF_chain: kernel returned!\n");
411 __asm("ta 2" : :);
412 }
413
414 static u_int stdin;
415 static u_int stdout;
416 static u_int mmuh = -1;
417 static u_int memh = -1;
418
419 void
420 setup()
421 {
422 u_int chosen;
423
424 if ((chosen = OF_finddevice("/chosen")) == -1)
425 _rtt();
426 if (OF_getprop(chosen, "stdin", &stdin, sizeof(stdin)) != sizeof(stdin)
427 || OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) != sizeof(stdout)
428 || OF_getprop(chosen, "mmu", &mmuh, sizeof(mmuh)) != sizeof(mmuh)
429 || OF_getprop(chosen, "memory", &memh, sizeof(memh)) != sizeof(memh))
430 _rtt();
431 }
432
433 /*
434 * The following need either the handle to memory or the handle to the MMU.
435 */
436
437 /*
438 * Grab some address space from the prom
439 *
440 * Only works while the prom is actively mapping us.
441 */
442 vaddr_t
443 OF_claim_virt(vaddr, len)
444 vaddr_t vaddr;
445 int len;
446 {
447 struct {
448 cell_t name;
449 cell_t nargs;
450 cell_t nreturns;
451 cell_t method;
452 cell_t ihandle;
453 cell_t align;
454 cell_t len;
455 cell_t vaddr;
456 cell_t status;
457 cell_t retaddr;
458 } args;
459
460 #ifdef __notyet
461 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
462 OF_printf("OF_claim_virt: cannot get mmuh\r\n");
463 return -1LL;
464 }
465 #endif
466 args.name = ADR2CELL("call-method");
467 args.nargs = 5;
468 args.nreturns = 2;
469 args.method = ADR2CELL("claim");
470 args.ihandle = HDL2CELL(mmuh);
471 args.align = 0;
472 args.len = len;
473 args.vaddr = ADR2CELL(vaddr);
474 if(openfirmware(&args) != 0)
475 return -1LL;
476 return args.retaddr; /* Kluge till we go 64-bit */
477 }
478
479 /*
480 * Request some address space from the prom
481 *
482 * Only works while the prom is actively mapping us.
483 */
484 vaddr_t
485 OF_alloc_virt(len, align)
486 int len;
487 int align;
488 {
489 int retaddr=-1;
490 struct {
491 cell_t name;
492 cell_t nargs;
493 cell_t nreturns;
494 cell_t method;
495 cell_t ihandle;
496 cell_t align;
497 cell_t len;
498 cell_t status;
499 cell_t retaddr;
500 } args;
501
502 #ifdef __notyet
503 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
504 OF_printf("OF_alloc_virt: cannot get mmuh\r\n");
505 return -1LL;
506 }
507 #endif
508 args.name = ADR2CELL("call-method");
509 args.nargs = 4;
510 args.nreturns = 2;
511 args.method = ADR2CELL("claim");
512 args.ihandle = mmuh;
513 args.align = align;
514 args.len = len;
515 args.retaddr = ADR2CELL(&retaddr);
516 if(openfirmware(&args) != 0)
517 return -1LL;
518 return (vaddr_t)args.retaddr; /* Kluge till we go 64-bit */
519 }
520
521 /*
522 * Release some address space to the prom
523 *
524 * Only works while the prom is actively mapping us.
525 */
526 int
527 OF_free_virt(vaddr, len)
528 vaddr_t vaddr;
529 int len;
530 {
531 struct {
532 cell_t name;
533 cell_t nargs;
534 cell_t nreturns;
535 cell_t method;
536 cell_t ihandle;
537 cell_t len;
538 cell_t vaddr;
539 } args;
540
541 #ifdef __notyet
542 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
543 OF_printf("OF_claim_virt: cannot get mmuh\r\n");
544 return -1;
545 }
546 #endif
547 args.name = ADR2CELL("call-method");
548 args.nargs = 4;
549 args.nreturns = 0;
550 args.method = ADR2CELL("release");
551 args.ihandle = HDL2CELL(mmuh);
552 args.vaddr = ADR2CELL(vaddr);
553 args.len = len;
554 return openfirmware(&args);
555 }
556
557
558 /*
559 * Unmap some address space
560 *
561 * Only works while the prom is actively mapping us.
562 */
563 int
564 OF_unmap_virt(vaddr, len)
565 vaddr_t vaddr;
566 int len;
567 {
568 struct {
569 cell_t name;
570 cell_t nargs;
571 cell_t nreturns;
572 cell_t method;
573 cell_t ihandle;
574 cell_t len;
575 cell_t vaddr;
576 } args;
577
578 #ifdef __notyet
579 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
580 OF_printf("OF_claim_virt: cannot get mmuh\r\n");
581 return -1;
582 }
583 #endif
584 args.name = ADR2CELL("call-method");
585 args.nargs = 4;
586 args.nreturns = 0;
587 args.method = ADR2CELL("unmap");
588 args.ihandle = HDL2CELL(mmuh);
589 args.vaddr = ADR2CELL(vaddr);
590 args.len = len;
591 return openfirmware(&args);
592 }
593
594 /*
595 * Have prom map in some memory
596 *
597 * Only works while the prom is actively mapping us.
598 */
599 vaddr_t
600 OF_map_phys(paddr, size, vaddr, mode)
601 paddr_t paddr;
602 off_t size;
603 vaddr_t vaddr;
604 int mode;
605 {
606 struct {
607 cell_t name;
608 cell_t nargs;
609 cell_t nreturns;
610 cell_t method;
611 cell_t ihandle;
612 cell_t mode;
613 cell_t size;
614 cell_t vaddr;
615 cell_t paddr_hi;
616 cell_t paddr_lo;
617 cell_t status;
618 cell_t retaddr;
619 } args;
620
621 #ifdef __notyet
622 if (mmuh == -1 && ((mmuh = get_mmu_handle()) == -1)) {
623 OF_printf("OF_map_phys: cannot get mmuh\r\n");
624 return 0LL;
625 }
626 #endif
627 args.name = ADR2CELL("call-method");
628 args.nargs = 7;
629 args.nreturns = 1;
630 args.method = ADR2CELL("map");
631 args.ihandle = HDL2CELL(mmuh);
632 args.mode = mode;
633 args.size = size;
634 args.vaddr = ADR2CELL(vaddr);
635 args.paddr_hi = ADR2CELL(paddr>>32);
636 args.paddr_lo = ADR2CELL(paddr);
637
638 if (openfirmware(&args) == -1)
639 return -1;
640 if (args.status)
641 return -1;
642 return (vaddr_t)args.retaddr;
643 }
644
645
646 /*
647 * Request some RAM from the prom
648 *
649 * Only works while the prom is actively mapping us.
650 */
651 paddr_t
652 OF_alloc_phys(len, align)
653 int len;
654 int align;
655 {
656 paddr_t paddr;
657 struct {
658 cell_t name;
659 cell_t nargs;
660 cell_t nreturns;
661 cell_t method;
662 cell_t ihandle;
663 cell_t align;
664 cell_t len;
665 cell_t status;
666 cell_t phys_hi;
667 cell_t phys_lo;
668 } args;
669
670 #ifdef __notyet
671 if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
672 OF_printf("OF_alloc_phys: cannot get memh\r\n");
673 return -1LL;
674 }
675 #endif
676 args.name = ADR2CELL("call-method");
677 args.nargs = 4;
678 args.nreturns = 3;
679 args.method = ADR2CELL("claim");
680 args.ihandle = HDL2CELL(memh);
681 args.align = align;
682 args.len = len;
683 if(openfirmware(&args) != 0)
684 return -1LL;
685 paddr = (paddr_t)(args.phys_hi<<32)|((unsigned int)(args.phys_lo));
686 return paddr; /* Kluge till we go 64-bit */
687 }
688
689 /*
690 * Request some specific RAM from the prom
691 *
692 * Only works while the prom is actively mapping us.
693 */
694 paddr_t
695 OF_claim_phys(phys, len)
696 paddr_t phys;
697 int len;
698 {
699 paddr_t paddr;
700 struct {
701 cell_t name;
702 cell_t nargs;
703 cell_t nreturns;
704 cell_t method;
705 cell_t ihandle;
706 cell_t align;
707 cell_t len;
708 cell_t phys_hi;
709 cell_t phys_lo;
710 cell_t status;
711 cell_t res;
712 cell_t rphys_hi;
713 cell_t rphys_lo;
714 } args;
715
716 #ifdef __notyet
717 if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
718 OF_printf("OF_alloc_phys: cannot get memh\r\n");
719 return 0LL;
720 }
721 #endif
722 args.name = ADR2CELL("call-method");
723 args.nargs = 6;
724 args.nreturns = 4;
725 args.method = ADR2CELL("claim");
726 args.ihandle = HDL2CELL(memh);
727 args.align = 0;
728 args.len = len;
729 args.phys_hi = HDL2CELL(phys>>32);
730 args.phys_lo = HDL2CELL(phys);
731 if(openfirmware(&args) != 0)
732 return 0LL;
733 paddr = (paddr_t)(args.rphys_hi<<32)|((unsigned int)(args.rphys_lo));
734 return paddr;
735 }
736
737 /*
738 * Free some RAM to prom
739 *
740 * Only works while the prom is actively mapping us.
741 */
742 int
743 OF_free_phys(phys, len)
744 paddr_t phys;
745 int len;
746 {
747 struct {
748 cell_t name;
749 cell_t nargs;
750 cell_t nreturns;
751 cell_t method;
752 cell_t ihandle;
753 cell_t len;
754 cell_t phys_hi;
755 cell_t phys_lo;
756 } args;
757
758 #ifdef __notyet
759 if (memh == -1 && ((memh = get_memory_handle()) == -1)) {
760 OF_printf("OF_free_phys: cannot get memh\r\n");
761 return -1;
762 }
763 #endif
764 args.name = ADR2CELL("call-method");
765 args.nargs = 5;
766 args.nreturns = 0;
767 args.method = ADR2CELL("release");
768 args.ihandle = HDL2CELL(memh);
769 args.len = len;
770 args.phys_hi = HDL2CELL(phys>>32);
771 args.phys_lo = HDL2CELL(phys);
772 return openfirmware(&args);
773 }
774
775
776 /*
777 * Claim virtual memory -- does not map it in.
778 */
779
780 void *
781 OF_claim(virt, size, align)
782 void *virt;
783 u_int size;
784 u_int align;
785 {
786 #define SUNVMOF
787 #ifndef SUNVMOF
788 struct {
789 cell_t name;
790 cell_t nargs;
791 cell_t nreturns;
792 cell_t virt;
793 cell_t size;
794 cell_t align;
795 cell_t baseaddr;
796 } args;
797
798
799 args.name = ADR2CELL("claim");
800 args.nargs = 3;
801 args.nreturns = 1;
802 args.virt = virt;
803 args.size = size;
804 args.align = align;
805 if (openfirmware(&args) == -1)
806 return (void *)-1;
807 return args.baseaddr;
808 #else
809 /*
810 * Sun Ultra machines run the firmware with VM enabled,
811 * so you need to handle allocating and mapping both
812 * virtual and physical memory. Ugh.
813 */
814
815 paddr_t paddr;
816 void* newvirt = NULL;
817
818 if (virt == NULL) {
819 if ((virt = (void*)OF_alloc_virt(size, align)) == (void*)-1) {
820 printf("OF_alloc_virt(%d,%d) failed w/%x\n", size, align, virt);
821 return (void *)-1;
822 }
823 } else {
824 if ((newvirt = (void*)OF_claim_virt((vaddr_t)virt, size)) == (void*)-1) {
825 printf("OF_claim_virt(%x,%d) failed w/%x\n", virt, size, newvirt);
826 return (void *)-1;
827 }
828 }
829 if ((paddr = OF_alloc_phys(size, align)) == -1) {
830 printf("OF_alloc_phys(%d,%d) failed\n", size, align);
831 OF_free_virt((vaddr_t)virt, size);
832 return (void *)-1;
833 }
834 if (OF_map_phys(paddr, size, (vaddr_t)virt, -1) == -1) {
835 printf("OF_map_phys(%x,%d,%x,%d) failed\n", paddr, size, virt, -1);
836 OF_free_phys((paddr_t)paddr, size);
837 OF_free_virt((vaddr_t)virt, size);
838 return (void *)-1;
839 }
840 return (void *)virt;
841 #endif
842 }
843
844
845 void
846 putchar(c)
847 int c;
848 {
849 char ch = c;
850
851 if (c == '\n')
852 putchar('\r');
853 OF_write(stdout, &ch, 1);
854 }
855
856 int
857 getchar()
858 {
859 unsigned char ch = '\0';
860 int l;
861
862 while ((l = OF_read(stdin, &ch, 1)) != 1)
863 if (l != -2 && l != 0)
864 return -1;
865 return ch;
866 }
867