Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / boot / pc98 / boot2 / bios.S
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:34:26  rpd
27  * $FreeBSD: src/sys/boot/pc98/boot2/bios.S,v 1.2.2.2 2003/01/13 08:52:53 nyan Exp $
28  */
29
30 /*
31   Copyright 1988, 1989, 1990, 1991, 1992 
32    by Intel Corporation, Santa Clara, California.
33
34                 All Rights Reserved
35
36 Permission to use, copy, modify, and distribute this software and
37 its documentation for any purpose and without fee is hereby
38 granted, provided that the above copyright notice appears in all
39 copies and that both the copyright notice and this permission notice
40 appear in supporting documentation, and that the name of Intel
41 not be used in advertising or publicity pertaining to distribution
42 of the software without specific, written prior permission.
43
44 INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
45 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
46 IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR
47 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
48 LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT,
49 NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
50 WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
51 */
52 /*
53  * Ported to PC-9801 by Yoshio Kimura
54  */
55
56 /*
57  * Extensions for El Torito CD-ROM booting:
58  *
59  * Copyright © 1997 Pluto Technologies International, Inc.  Boulder CO
60  * Copyright © 1997 interface business GmbH, Dresden.
61  *      All rights reserved.
62  *
63  * This code has been written by Jörg Wunsch, Dresden.
64  * Direct comments to <joerg_wunsch@interface-business.de>.
65  *
66  * Redistribution and use in source and binary forms, with or without
67  * modification, are permitted provided that the following conditions
68  * are met:
69  * 1. Redistributions of source code must retain the above copyright
70  *    notice, this list of conditions and the following disclaimer.
71  * 2. Redistributions in binary form must reproduce the above copyright
72  *    notice, this list of conditions and the following disclaimer in the
73  *    documentation and/or other materials provided with the distribution.
74  *
75  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
76  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
77  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
78  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
79  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
80  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
81  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
82  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
83  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
84  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
85  * POSSIBILITY OF SUCH DAMAGE.
86  *
87  */
88
89         .file   "bios.s"
90
91 #include "asm.h"
92         .text
93
94 #ifndef CDBOOT
95
96 /*
97  *  PC-9801/PC-9821 SCSI MO booting
98  *    2002/06/05-07/03 Kawanobe Koh <kawanobe@st.rim.or.jp>
99  *
100  */
101 scsi_hd:
102         .code16
103         push    %cx
104         push    %ds
105         mov     %bl, %cl                /* UA */
106         and     $0x0F, %cl
107         xor     %ax, %ax
108         mov     %ax, %ds
109         mov     (0x0482), %al           /* SCSI HD equipment bits */
110         shr     %cl, %al
111         pop     %ds
112         pop     %cx
113         test    $1, %al
114         ret
115
116 /*
117  * biosread(dev, cyl, head, sec, nsec, offset)
118  *      Read "nsec" sectors from disk to offset "offset" in boot segment
119  * BIOS call "INT 0x1B Function 0xn6" to read sectors from disk into memory
120  *      Call with       %ah = 0xd6(for floppy disk) or 0x06(for hard disk)
121  *                      %al = DA/UA
122  *                      %bx = data length
123  *                      %ch = sector size(for floppy) or cylinder(for hard)
124  *                      %cl = cylinder
125  *                      %dh = head
126  *                      %dl = sector
127  *                      %es:%bp = segment:offset of buffer
128  *      Return:         
129  *                      %al = 0x0 on success; err code on failure
130  */
131
132 ENTRY(biosread)
133         .code32
134         push    %ebp
135         mov     %esp, %ebp
136
137         push    %ebx
138         push    %esi
139         push    %edi
140
141         mov     0x08(%ebp), %bl         /* (byte) DA/UA */
142         mov     0x0C(%ebp), %ecx        /* (word) cylinder */
143         mov     0x10(%ebp), %dh         /* (byte) head */
144         mov     0x14(%ebp), %dl         /* (byte) sector */
145         mov     0x18(%ebp), %esi        /* (byte) number of sectors */
146         mov     0x1C(%ebp), %edi        /* (word) destination offset */
147
148         /* prot_to_real will set %es to BOOTSEG */
149         call    EXT(prot_to_real)       /* enter real mode */
150         .code16
151         mov     $0x06, %bh              /* read data function */
152         mov     %bl, %al                /* DA */
153         and     $0xF0, %al
154         cmp     $0x30, %al              /* 1440KB FD */
155         jz      read_floppy
156         cmp     $0x90, %al              /* 1200KB FD */
157         jz      read_floppy
158         cmp     $0xA0, %al              /* SCSI HD or MO */
159         jnz     read_next
160         call    scsi_hd
161         jnz     read_next
162 read_linear:
163         mov     %dh, %al                /* change to linear sector */
164         shl     $5, %al                 /* multiply by 32 sector per track */
165         add     %dl, %al
166         xor     %dh, %dh                /* higher 16 bits into %dx */
167         mov     %ch, %dl
168         mov     %cl, %ch                /* lower 16 bits into %cx */
169         mov     %al, %cl
170         and     $0x7F, %bl              /* linear access DA/UA */
171         jmp     read_next
172 read_floppy:
173         inc     %dx                     /* sector address begins from one */
174         mov     $0x02, %ch              /* 512 bytes sector */
175         mov     $0xD6, %bh              /* MT MFM retry seek */
176 read_next:
177         mov     %si, %ax                /* number of sectors */
178         shl     $9, %ax                 /* multiply by 512 bytes */
179         xchg    %bx, %ax
180         mov     %di, %bp                /* destination offset */
181         int     $0x1B                   /* disk bios call */
182         jc      read_end
183         xor     %ax, %ax
184 read_end:
185         mov     %ax, %bx                /* save return value */
186
187         .code32
188         data32
189         call    EXT(real_to_prot)       /* back to protected mode */
190
191         xor     %eax, %eax
192         mov     %bh, %al                /* return value in %eax */
193
194         pop     %edi
195         pop     %esi
196         pop     %ebx
197         pop     %ebp
198
199         ret
200
201 #else /* CDBOOT */
202
203
204 /*
205  * int
206  * getbootspec(struct specpacket *offset)
207  *
208  * Read CD-ROM boot specification packet to "offset".
209  */
210 ENTRY(getbootspec)
211         push    %ebp
212         mov     %esp, %ebp
213
214         push    %esi
215         push    %ebx
216
217         movw    0x8(%ebp), %si
218         mov     $0x7f, %edx
219
220         /* prot_to_real will set %es to BOOTSEG */
221         call    EXT(prot_to_real)       /* enter real mode */
222         movw    $0x4b01, %ax            /* (do not) terminate disk emulation */
223         movb    $0x7f, %dl              /* any drive */
224
225         sti
226         int     $0x13
227         cli
228
229         /* save return value (actually movw %ax, %bx) */
230         mov     %eax, %ebx
231
232         data32
233         call    EXT(real_to_prot)       /* back to protected mode */
234
235         xor     %eax, %eax
236         movb    %bh, %al                /* return value in %ax */
237
238         pop     %ebx
239         pop     %esi
240         pop     %ebp
241
242         ret
243
244
245 /*
246  * int
247  * biosreadlba(struct daddrpacket *daddr)
248  *      Read sectors using the BIOS "read extended" function
249  * BIOS call "INT 0x13 Function 0x42" to read sectors from disk into memory
250  *      Call with       %ah = 0x42
251  *                      %dl = drive (0x0 for floppy disk, or emulated CD)
252  *                      %ds:%si = ptr to disk address packet
253  *      Return:
254  *                      %ah = 0x0 on success; err code on failure
255  */
256
257 ENTRY(biosreadlba)
258         push    %ebp
259         mov     %esp, %ebp
260
261         push    %ebx
262         push    %esi
263
264         movw    8(%ebp), %si
265         movl    $0, %edx                /* emulated CD is always drive 0 */
266
267         /* prot_to_real will set %es to BOOTSEG */
268         call    EXT(prot_to_real)       /* enter real mode */
269         movw    $0x4200, %ax            /* subfunction */
270         movb    $0, %dl
271
272         sti
273         int     $0x13
274         cli
275
276         /* save return value (actually movw %ax, %bx) */
277         mov     %eax, %ebx
278
279         data32
280         call    EXT(real_to_prot)       /* back to protected mode */
281
282         xor     %eax, %eax
283         movb    %bh, %al                /* return value in %ax */
284
285         pop     %esi
286         pop     %ebx
287         pop     %ebp
288
289         ret
290
291 #endif /* !CDBOOT */
292
293 /*
294  * getc()
295  * BIOS call "INT 18H Function 00H" to read character from keyboard
296  *      Call with       %ah = 0x0
297  *      Return:         %ah = keyboard scan code
298  *                      %al = ASCII character
299  */
300
301 ENTRY(getc)
302         .code32
303         push    %ebp
304         mov     %esp, %ebp
305         push    %ebx                    /* save %ebx */
306         push    %esi
307         push    %edi
308
309         call    EXT(prot_to_real)
310         .code16
311
312         movb    $0x0, %ah
313         int     $0x18
314
315         movb    %al, %bl                /* real_to_prot uses %eax */
316
317         .code32
318         data32
319         call    EXT(real_to_prot)
320
321         xor     %eax, %eax
322         movb    %bl, %al
323
324         pop     %edi
325         pop     %esi
326         pop     %ebx
327         pop     %ebp
328         ret
329 /*
330  * ischar()
331  *      if there is a character pending, return it; otherwise return 0
332  * BIOS call "INT 18H Function 01H" to check whether a character is pending
333  *      Call with       %ah = 0x1
334  *      Return:
335  *              If key waiting to be input:
336  *                      %ah = keyboard scan code
337  *                      %al = ASCII character
338  *                      %bh = 1
339  *              else
340  *                      %bh = 0
341  */
342 ENTRY(ischar)
343         .code32
344         push    %ebp
345         mov     %esp, %ebp
346         push    %ebx
347         push    %esi
348         push    %edi
349
350         call    EXT(prot_to_real)       /* enter real mode */
351
352         xor     %ebx, %ebx
353         .code16
354         movb    $0x1, %ah
355         int     $0x18
356         andb    %bh, %bh
357         data32
358         jz      nochar
359         movb    %al, %bl
360
361 nochar:
362         .code32
363         data32
364         call    EXT(real_to_prot)
365
366         xor     %eax, %eax
367         movb    %bl, %al
368
369         pop     %edi
370         pop     %esi
371         pop     %ebx
372         pop     %ebp
373         ret
374
375 /*
376  *
377  * get_diskinfo():  return a word that represents the
378  *      max number of sectors and heads and drives for this device
379  *
380  */
381
382 ENTRY(get_diskinfo)
383         .code32
384         push    %ebp
385         mov     %esp, %ebp
386         push    %ebx
387
388         mov     0x08(%ebp), %bl         /* (byte) DA/UA */
389
390         call    EXT(prot_to_real)       /* enter real mode */
391         .code16
392         mov     %bl, %al                /* DA */
393         and     $0xf0, %al
394         mov     $18, %dl                /* 1440KB FD sectors per track */
395         cmp     $0x30, %al
396         jz      floppy
397         mov     $15, %dl                /* 1200KB FD sectors per track */
398         cmp     $0x90, %al
399         jz      floppy
400         cmp     $0xA0, %al              /* SCSI HD or MO */
401         jnz     sense
402         call    scsi_hd
403         jnz     sense
404
405         push    %ds                     /* SCSI MO or CD ? */
406         xor     %ax, %ax
407         mov     %ax, %ds
408         and     $0x0F, %bx              /* UA */
409         shl     $2, %bx                 /* parameter offset */
410         add     $0x0460, %bx
411         mov     (%bx), %al              /* SCSI equipment parameter[0] */
412         and     $0x1F, %al              /* peripheral device type */
413         cmp     $7, %al                 /* SCSI MO */
414         jnz     good
415         add     $3, %bx
416         mov     (%bx), %al              /* SCSI equipment parameter[3] */
417         test    $0x30, %al              /* sector length from 256 to 2048 */
418         jnz     good
419         or      $0x10, %al              /* forced set 512 bytes sector */
420         mov     %al, (%bx)
421         mov     $0xA100, %dx            /* refered by C language */
422         mov     %dx, %ds
423         mov     %al, (%bx)
424 good:
425         pop     %ds
426
427         mov     $0xFFFE, %cx            /* virtual 65535 cylinders setting */
428         mov     $0x0820, %dx            /* standard 8 heads and 32 sectors */
429         jmp     ok
430 sense:
431         mov     $0x84, %ah              /* ask for disk info */
432         mov     %bl, %al
433         int     $0x1b
434         jnc     ok                      /* use %cx and %dx after */
435         /*
436          * Urk.  Call failed.  It is not supported for floppies by old BIOS's.
437          * Guess it's a 15-sector floppy.
438          */
439 floppy:
440         mov     $79, %cx                /* 80 cylinders 1200K and 1440K FD */
441         mov     $2, %dh                 /* 2 heads as double side */
442 ok:
443         .code32
444         data32
445         call    EXT(real_to_prot)       /* back to protected mode */
446
447         /* 
448          * form a longword representing all this gunk:
449          *      16 bit cylinder
450          *       8 bit head
451          *       8 bit sector
452          */
453         mov     %ecx, %eax
454         sal     $16, %eax               /* max cylinder number from zero */
455         mov     %dx, %ax                /* number of heads and sectors */
456
457         pop     %ebx
458         pop     %ebp
459         ret
460
461 /*
462  *
463  * memsize(i) :  return the memory size in KB. i == 0 for conventional memory,
464  *              i == 1 for extended memory
465  *              Both have the return value in AX.
466  *
467  */
468
469 ENTRY(memsize)
470         .code32
471         push    %ebp
472         mov     %esp, %ebp
473         push    %ebx
474         push    %esi
475         push    %edi
476
477         mov     8(%ebp), %ebx
478
479         xor     %eax, %eax
480         cmpb    $0x01, %bl
481         jnz     memcnv
482 memext:
483         movb    0xA1401 - BOOTSEG * 0x10, %al
484         shll    $7, %eax
485         xorl    %ebx, %ebx
486         movw    0xA1594 - BOOTSEG * 0x10, %bx
487         shll    $10, %ebx
488         addl    %ebx, %eax
489         jmp     xdone
490
491 memcnv:
492         movb    0xA1501 - BOOTSEG * 0x10, %al
493         andb    $0x07, %al
494         incl    %eax
495         shll    $7, %eax
496
497 xdone:
498         pop     %edi
499         pop     %esi
500         pop     %ebx
501         pop     %ebp
502         ret