1/*-
2 * Copyright (c) 2008-2009 TAKAHASHI Yoshihiro
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: stable/11/stand/pc98/boot2/boot1.S 229462 2012-01-04 03:49:41Z nyan $
27 */
28
29/* Memory Locations */
30		.set STACK_OFF,0x6000		# Stack offset
31		.set LOAD_SIZE,8192		# Load size
32		.set DAUA,0x0584		# DA/UA
33		.set MEM_REL,0x700		# Relocation address
34		.set MEM_ARG,0x900		# Arguments
35		.set MEM_BUF,0x8cec		# Load area
36		.set MEM_BTX,0x9000		# BTX start
37		.set MEM_JMP,0x9010		# BTX entry point
38		.set MEM_USR,0xa000		# Client start
39
40/* PC98 machine type from sys/pc98/pc98/pc98_machdep.h */
41		.set MEM_SYS,		0xa100	# System common area segment
42		.set PC98_MACHINE_TYPE,	0x0620	# PC98 machine type
43		.set EPSON_ID,		0x0624	# EPSON machine id
44
45		.set M_NEC_PC98,	0x0001
46		.set M_EPSON_PC98,	0x0002
47		.set M_NOT_H98,		0x0010
48		.set M_H98,		0x0020
49		.set M_NOTE,		0x0040
50		.set M_NORMAL,		0x1000
51		.set M_8M,		0x8000
52
53/* Partition Constants */
54		.set PRT_OFF,0x1be		# Partition offset
55
56/* Misc. Constants */
57		.set SIZ_PAG,0x1000		# Page size
58		.set SIZ_SEC,0x200		# Sector size
59
60		.set NSECT,0x10
61
62		.globl start
63		.globl read
64		.globl putc
65		.code16
66
67start:		jmp main
68
69boot_cyl:	.org 4
70		.ascii "IPL1   "
71
72main:		cld
73
74		/* Setup the stack */
75		xor %si,%si
76		mov %si,%ss
77		mov $STACK_OFF,%sp
78
79		push %cx
80
81		/* Relocate ourself to MEM_REL */
82		push %cs
83		pop %ds
84		mov %si,%es
85		mov $MEM_REL,%di
86		mov $SIZ_SEC,%cx
87		rep
88		movsb
89
90		/* Transfer PC-9801 system common area */
91		xor %ax,%ax
92		mov %ax,%si
93		mov %ax,%ds
94		mov %ax,%di
95		mov $MEM_SYS,%ax
96		mov %ax,%es
97		mov $0x0600,%cx
98		rep
99		movsb
100
101		/* Transfer EPSON machine type */
102		mov $0xfd00,%ax
103		mov %ax,%ds
104		mov (0x804),%eax
105		and $0x00ffffff,%eax
106		mov %eax,%es:(EPSON_ID)
107
108		/* Set machine type to PC98_SYSTEM_PARAMETER */
109#ifdef SET_MACHINE_TYPE
110		call set_machine_type
111#else
112		mov $M_NEC_PC98+M_NOT_H98,%eax
113		mov %eax,%es:(PC98_MACHINE_TYPE)
114#endif
115
116		/* Setup graphic screen */
117		mov $0x42,%ah		/* 640x400 */
118		mov $0xc0,%ch
119		int $0x18
120		mov $0x40,%ah		/* graph on */
121		int $0x18
122
123		/* Setup text screen */
124		mov $0x0a00,%ax		/* 80x25 */
125		int $0x18
126		mov $0x0c,%ah		/* text on */
127		int $0x18
128		mov $0x13,%ah		/* cursor home */
129		xor %dx,%dx
130		int $0x18
131		mov $0x11,%ah		/* cursor on */
132		int $0x18
133
134		/* Setup keyboard */
135		mov $0x03,%ah
136		int $0x18
137
138		pop %cx
139
140		/* bootstrap passes */
141		xor %edi,%edi
142		mov %di,%ds
143		mov %di,%es
144		mov %cs,%bx
145		cmp $0x1fe0,%bx
146		jz boot_fd
147		cmp $0x1fc0,%bx
148		jnz boot_hd
149		xor %cx,%cx
150		mov (DAUA),%al
151		and $0xf0,%al
152		cmp $0x30,%al
153		jz boot_fd
154		cmp $0x90,%al
155		jnz boot_hd
156boot_fd:	xor %cx,%cx
157		jmp boot_load
158boot_hd:	test %cx,%cx
159		jnz boot_load
160		mov %cs:(boot_cyl),%cx
161boot_load:	mov %cx,MEM_ARG		/* Save cylinder number */
162		mov %cx,%di
163		xor %dx,%dx
164		mov $LOAD_SIZE,%bx
165		mov $MEM_BUF,%bp
166		push %cs
167		callw read
168		jc error
169
170		/* Transfer boot2.bin */
171		mov $MEM_BTX,%bx
172		mov 0xa(%bx),%si	/* BTX size */
173		add %bx,%si		/* start of boot2.bin */
174		mov $MEM_USR+SIZ_PAG*2,%di
175		mov $MEM_BTX+(NSECT-1)*SIZ_SEC,%cx
176		sub %si,%cx
177		rep
178		movsb
179
180		/* Enable A20 */
181		xor %ax,%ax
182		outb %al,$0xf2
183		mov $0x02,%al
184		outb %al,$0xf6
185
186		/* Start BTX */
187		ljmp $0x0000,$MEM_JMP
188
189/*
190 * Reads sectors from the disk.
191 * Call with:
192 *
193 * %bx		- bytes to read
194 * %cx		- cylinder
195 * %dh		- head
196 * %dl		- sector
197 * %edi		- lba
198 * %es:(%bp)	- buffer to read data into
199 */
200read:		xor %ax,%ax
201		mov %ax,%ds
202		mov $0x06,%ah
203		mov (DAUA),%al
204		mov %ax,%si
205		and $0xf0,%al
206		cmp $0x30,%al		/* 1.44MB FDD */
207		jz read_fd
208		cmp $0x90,%al		/* 1MB FDD */
209		jz read_fd
210		cmp $0xa0,%al		/* Is SCSI device? */
211		jnz read_load
212		push %cx
213		mov %si,%cx
214		and $0x0f,%cl
215		inc %cl
216		mov (0x482),%ah
217		shr %cl,%ah		/* Is SCSI HDD? */
218		pop %cx
219		jc read_load
220		and $0xff7f,%si		/* SCSI MO */
221		mov %di,%cx
222		shr $16,%edi
223		mov %di,%dx
224		jmp read_load
225read_fd:	or $0xd000,%si
226		or $0x0200,%cx
227		inc %dx
228read_load:	mov %si,%ax
229		int $0x1b
230		lret
231
232/*
233 * Print out the error message, wait for a keypress, and then reboot
234 * the machine.
235 */
236error:		push %cs
237		pop %ds
238		mov $msg_eread,%si
239		call putstr
240		xor %ax,%ax		/* Get keypress */
241		int $0x18
242		xor %ax,%ax		/* CPU reset */
243		outb %al,$0xf0
244halt:		hlt
245		jmp halt		/* Spin */
246
247/*
248 * Display a null-terminated string.
249 */
250putstr.0:	push %cs
251		callw putc
252putstr:		lodsb
253		test %al,%al
254		jne putstr.0
255		ret
256
257/*
258 * Display a single char.
259 */
260putc:		pusha
261		xor %dx,%dx
262		mov %dx,%ds
263		mov MEM_REL+cursor-start,%di
264		mov $0xa000,%bx
265		mov %bx,%es
266		mov $(80*2),%cx
267
268		cmp $0x08,%al
269		je putc.bs
270		cmp $0x0d,%al
271		je putc.cr
272		cmp $0x0a,%al
273		je putc.lf
274		cmp $0x5c,%al			/* \ */
275		jne 1f
276		mov $0xfc,%al
2771:		movb $0xe1,%es:0x2000(%di)
278		stosw
279		jmp putc.scr
280putc.bs:	test %di,%di
281		jz putc.move
282		dec %di
283		dec %di
284		movb $0xe1,%es:0x2000(%di)
285		movw $0x20,%es:(%di)
286		jmp putc.move
287putc.cr:	mov %di,%ax
288		div %cx
289		sub %dx,%di
290		jmp putc.move
291putc.lf:	add %cx,%di
292putc.scr:	cmp $(80*2*25),%di		/* Scroll screen */
293		jb putc.move
294		push %ds
295		mov %bx,%ds
296		mov $(80*2),%si
297		xor %di,%di
298		mov $(80*24/2),%cx
299		rep
300		movsl
301		xor %ax,%ax
302		mov $0x20,%al
303		mov $80,%cl
304		rep
305		stosw
306		pop %ds
307		mov $(80*24*2),%di
308putc.move:	mov %di,MEM_REL+cursor-start	/* Move cursor */
309		mov $0x13,%ah
310		mov %di,%dx
311		int $0x18
312		popa
313		lret
314
315cursor:		.word 0
316
317#ifdef SET_MACHINE_TYPE
318/*
319 * Set machine type to PC98_SYSTEM_PARAMETER.
320 */
321set_machine_type:
322		xor %edx,%edx
323		mov %dx,%ds
324//		mov $MEM_SYS,%ax
325//		mov %ax,%es
326
327		/* Wait V-SYNC */
328vsync.1:	inb $0x60,%al
329		test $0x20,%al
330		jnz vsync.1
331vsync.2:	inb $0x60,%al
332		test $0x20,%al
333		jz vsync.2
334
335		/* ANK 'A' font */
336		xor %al,%al
337		outb %al,$0xa1
338		mov $0x41,%al
339		outb %al,$0xa3
340
341		/* Get 'A' font from CG window */
342		push %ds
343		mov $0xa400,%ax
344		mov %ax,%ds
345		xor %eax,%eax
346		xor %bx,%bx
347		mov $4,%cx
348font.1:		add (%bx),%eax
349		add $4,%bx
350		loop font.1
351		pop %ds
352		cmp $0x6efc58fc,%eax
353		jnz m_epson
354
355m_pc98:		or $M_NEC_PC98,%edx
356		mov $0x0458,%bx
357		mov (%bx),%al
358		test $0x80,%al
359		jz m_not_h98
360		or $M_H98,%edx
361		jmp 1f
362m_epson:	or $M_EPSON_PC98,%edx
363m_not_h98:	or $M_NOT_H98,%edx
364
3651:		inb $0x42,%al
366		test $0x20,%al
367		jz 1f
368		or $M_8M,%edx
369
3701:		mov $0x0400,%bx
371		mov (%bx),%al
372		test $0x80,%al
373		jz 1f
374		or $M_NOTE,%edx
375
3761:		mov $PC98_MACHINE_TYPE,%bx
377		mov %edx,%es:(%bx)
378		ret
379#endif
380
381/* Messages */
382
383msg_eread:	.asciz "Error\r\n"
384
385		.org PRT_OFF,0x90
386
387/* Partition table */
388
389		.fill 0x30,0x1,0x0
390		.byte 0x80, 0x00, 0x01, 0x00
391		.byte 0xa5, 0xff, 0xff, 0xff
392		.byte 0x00, 0x00, 0x00, 0x00
393		.byte 0x50, 0xc3, 0x00, 0x00
394
395		.word 0xaa55			# Magic number
396