]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/boot/pc98/boot2/io.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / boot / pc98 / boot2 / io.c
1 /*
2  * Mach Operating System
3  * Copyright (c) 1992, 1991 Carnegie Mellon University
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify and distribute this software and its
7  * documentation is hereby granted, provided that both the copyright
8  * notice and this permission notice appear in all copies of the
9  * software, derivative works or modified versions, and any portions
10  * thereof, and that both notices appear in supporting documentation.
11  *
12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15  *
16  * Carnegie Mellon requests users of this software to return to
17  *
18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19  *  School of Computer Science
20  *  Carnegie Mellon University
21  *  Pittsburgh PA 15213-3890
22  *
23  * any improvements or extensions that they make and grant Carnegie Mellon
24  * the rights to redistribute these changes.
25  *
26  *      from: Mach, Revision 2.2  92/04/04  11:35:57  rpd
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include "boot.h"
33 #include <machine/cpufunc.h>
34 #include <sys/reboot.h>
35 #include <pc98/pc98/pc98_machdep.h>
36
37 static int getchar(int in_buf);
38
39 /*
40  * Gate A20 for high memory
41  */
42 void
43 gateA20(void)
44 {
45         outb(0xf2, 0x00);
46         outb(0xf6, 0x02);
47 }
48
49 /* printf - only handles %d as decimal, %c as char, %s as string */
50
51 void
52 printf(const char *format, ...)
53 {
54         int *dataptr = (void *)&format;
55         char c;
56
57         dataptr++;
58         while ((c = *format++))
59                 if (c != '%')
60                         putchar(c);
61                 else
62                         switch (c = *format++) {
63                               case 'd': {
64                                       int num = *dataptr++;
65                                       char buf[10], *ptr = buf;
66                                       if (num<0) {
67                                               num = -num;
68                                               putchar('-');
69                                       }
70                                       do
71                                               *ptr++ = '0'+num%10;
72                                       while (num /= 10);
73                                       do
74                                               putchar(*--ptr);
75                                       while (ptr != buf);
76                                       break;
77                               }
78                               case 'x': {
79                                       unsigned int num = *dataptr++, dig;
80                                       char buf[8], *ptr = buf;
81                                       do
82                                               *ptr++ = (dig=(num&0xf)) > 9?
83                                                         'a' + dig - 10 :
84                                                         '0' + dig;
85                                       while (num >>= 4);
86                                       do
87                                               putchar(*--ptr);
88                                       while (ptr != buf);
89                                       break;
90                               }
91                               case 'c': putchar((*dataptr++)&0xff); break;
92                               case 's': {
93                                       char *ptr = (char *)*dataptr++;
94                                       while ((c = *ptr++))
95                                               putchar(c);
96                                       break;
97                               }
98                         }
99 }
100
101 void
102 putchar(int c)
103 {
104         if (c == '\n')
105                 putchar('\r');
106         if (loadflags & RB_DUAL) {
107                 putc(c);
108                 serial_putc(c);
109         } else if (loadflags & RB_SERIAL)
110                 serial_putc(c);
111         else
112                 putc(c);
113 }
114
115 static int
116 getchar(int in_buf)
117 {
118         int c;
119
120 loop:
121         if (loadflags & RB_DUAL) {
122                 if (ischar())
123                         c = getc();
124                 else if (serial_ischar())
125                         c = serial_getc();
126                 else
127                         goto loop;
128         } else if (loadflags & RB_SERIAL)
129                 c = serial_getc();
130         else
131                 c = getc();
132         if (c == '\r')
133                 c = '\n';
134         if (c == '\b') {
135                 if (in_buf != 0) {
136                         putchar('\b');
137                         putchar(' ');
138                 } else {
139                         goto loop;
140                 }
141         }
142         putchar(c);
143         return(c);
144 }
145
146 /*
147  * This routine uses an inb to an unused port, the time to execute that
148  * inb is approximately 1.25uS.  This value is pretty constant across
149  * all CPU's and all buses, with the exception of some PCI implentations
150  * that do not forward this I/O address to the ISA bus as they know it
151  * is not a valid ISA bus address, those machines execute this inb in
152  * 60 nS :-(.
153  *
154  * XXX this should be converted to use bios_tick.
155  */
156 void
157 delay1ms(void)
158 {
159         int i = 800;
160
161         while (--i >= 0)
162             (void)outb(0x5f,0);         /* about 600ns */
163 }
164
165 static __inline int
166 isch(void)
167 {
168         int isc;
169
170         /*
171          * Checking the keyboard has the side effect of enabling clock
172          * interrupts so that bios_tick works.  Check the keyboard to
173          * get this side effect even if we only want the serial status.
174          */
175         isc = ischar();
176
177         if (loadflags & RB_DUAL) {
178                 if (isc != 0)
179                         return (isc);
180         } else if (!(loadflags & RB_SERIAL))
181                 return (isc);
182         return (serial_ischar());
183 }
184
185 static __inline unsigned
186 pword(unsigned physaddr)
187 {
188         static int counter = 0;
189         int i;
190
191         for (i = 0; i < 512; i++)
192                 (void)outb(0x5f, 0);
193
194         return (counter++);
195 }
196
197 int
198 gets(char *buf)
199 {
200 #define bios_tick               pword(0x46c)
201 #define BIOS_TICK_MS            1
202         unsigned initial_bios_tick;
203         char *ptr=buf;
204
205 #if BOOTWAIT
206         for (initial_bios_tick = bios_tick;
207              bios_tick - initial_bios_tick < BOOTWAIT / BIOS_TICK_MS;)
208 #endif
209                 if (isch())
210                         for (;;) {
211                                 switch(*ptr = getchar(ptr - buf) & 0xff) {
212                                       case '\n':
213                                       case '\r':
214                                         *ptr = '\0';
215                                         return 1;
216                                       case '\b':
217                                         if (ptr > buf) ptr--;
218                                         continue;
219                                       default:
220                                         ptr++;
221                                 }
222 #if TIMEOUT + 0
223 #if !BOOTWAIT
224 #error "TIMEOUT without BOOTWAIT"
225 #endif
226                                 for (initial_bios_tick = bios_tick;;) {
227                                         if (isch())
228                                                 break;
229                                         if (bios_tick - initial_bios_tick >=
230                                             TIMEOUT / BIOS_TICK_MS)
231                                         return 0;
232                                 }
233 #endif
234                         }
235         return 0;
236 }
237
238 int
239 strcmp(const char *s1, const char *s2)
240 {
241         while (*s1 == *s2) {
242                 if (!*s1++)
243                         return 0;
244                 s2++;
245         }
246         return 1;
247 }
248
249 #ifdef CDBOOT
250 int
251 strcasecmp(const char *s1, const char *s2)
252 {
253         /*
254          * We only consider ASCII chars and don't anticipate
255          * control characters (they are invalid in filenames
256          * anyway).
257          */
258         while ((*s1 & 0x5f) == (*s2 & 0x5f)) {
259                 if (!*s1++)
260                         return 0;
261                 s2++;
262         }
263         return 1;
264 }
265 #endif /* !CDBOOT */
266
267 void
268 memcpy(const void *from, void *to, size_t len)
269 {
270         const char *fp = (const char *)from;
271         char *tp = (char *)to;
272
273         while (len-- > 0)
274                 *tp++ = *fp++;
275 }
276
277 /* To quote Ken: "You are not expected to understand this." :) */
278
279 void
280 twiddle(void)
281 {
282         putchar((char)tw_chars);
283         tw_chars = (tw_chars >> 8) | ((tw_chars & (unsigned long)0xFF) << 24);
284         putchar('\b');
285 }
286
287 static unsigned short *Crtat = (unsigned short *)0;
288 static int row;
289 static int col;
290
291 void putc(int c)
292 {
293         static unsigned short *crtat;
294         unsigned char sys_type;
295         unsigned short *cp;
296         int i, pos;
297
298         if (Crtat == 0) {
299                 sys_type = *(unsigned char *)V(0xA1501);
300                 if (sys_type & 0x08) {
301                         Crtat = (unsigned short *)V(0xE0000);
302                         crtat = Crtat;
303                         row = 31;
304                         col = 80;
305                 } else {
306                         Crtat = (unsigned short *)V(0xA0000);
307                         crtat = Crtat;
308                         row = 25;
309                         col = 80;
310                 }
311         }
312
313         switch(c) {
314         case '\t':
315                 do {
316                         putc(' ');
317                 } while ((int)crtat % 16);
318                 break;
319         case '\b':
320                 crtat--;
321                 break;
322         case '\r':
323                 crtat -= (crtat - Crtat) % col;
324                 break;
325         case '\n':
326                 crtat += col;
327                 break;
328         default:
329                 *crtat = (c == 0x5c ? 0xfc : c);
330                 *(crtat++ + 0x1000) = 0xe1;
331                 break;
332         }
333
334         if (crtat >= Crtat + col * row) {
335                 cp = Crtat;
336                 for (i = 1; i < row; i++) {
337                         memcpy((void *)(cp+col), (void *)cp, col*2);
338                         cp += col;
339                 }
340                 for (i = 0; i < col; i++) {
341                         *cp++ = ' ';
342                 }
343                 crtat -= col;
344         }
345         pos = crtat - Crtat;
346         while((inb(0x60) & 0x04) == 0) {}
347         outb(0x62, 0x49);
348         outb(0x60, pos & 0xff);
349         outb(0x60, pos >> 8);
350 }
351
352 void machine_check(void)
353 {
354         int     ret;
355         int     i;
356         int     data = 0;
357         
358         /* PC98_SYSTEM_PARAMETER(0x501) */
359         ret = ((*(unsigned char*)V(0xA1501)) & 0x08) >> 3;
360
361         /* Wait V-SYNC */
362         while (inb(0x60) & 0x20) {}
363         while (!(inb(0x60) & 0x20)) {}
364
365         /* ANK 'A' font */
366         outb(0xa1, 0x00);
367         outb(0xa3, 0x41);
368
369         /* M_NORMAL, use CG window (all NEC OK)  */
370         /* sum */
371         for (i = 0; i < 4; i++) {
372                 data += *((unsigned long*)V(0xA4000) + i);/* 0xa4000 */
373         }
374         if (data == 0x6efc58fc) { /* DA data */
375                 ret |= M_NEC_PC98;
376         } else {
377                 ret |= M_EPSON_PC98;
378         }
379         ret |= (inb(0x42) & 0x20) ? M_8M : 0;
380
381         /* PC98_SYSTEM_PARAMETER(0x400) */
382         if ((*(unsigned char*)V(0xA1400)) & 0x80) {
383                 ret |= M_NOTE;
384         }
385         if (ret & M_NEC_PC98) {
386                 /* PC98_SYSTEM_PARAMETER(0x458) */
387                 if ((*(unsigned char*)V(0xA1458)) & 0x80) {
388                         ret |= M_H98;
389                 } else {
390                         ret |= M_NOT_H98;
391                 }
392         } else
393                 ret |= M_NOT_H98;
394
395         (*(unsigned long *)V(0xA1620)) = ret;
396 }