This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / sys / i386 / stand / asbootblk.c
CommitLineData
15637ed4
RG
1/*
2 * sys/i386/stand/asbootblk.c
3 *
4 * Boot block for Adaptech 1542 SCSI
5 *
6 * April 10, 1992
7 * Pace Willisson
8 * pace@blitz.com
9 *
10 * Placed in the public domain with NO WARRANTIES, not even the
11 * implied warranties for MERCHANTABILITY or FITNESS FOR A
12 * PARTICULAR PURPOSE.
13 *
14 * To compile:
15 *
16 * cc -O -c -DRELOC=0x70000 asbootblk.c
17 * ld -N -T 7c00 asbootblk.o
18 *
19 * This should result in a file with 512 bytes of text and no initialized
20 * data. Strip the 32 bit header and place in block 0.
21 *
22 * When run, this program copies at least the first 8 blocks of SCSI
23 * target 0 to the address specified by RELOC, then jumps to the
24 * address RELOC+1024 (skipping the boot block and disk label). Usually,
25 * disks have 512 bytes per block, but I don't think they ever have
26 * less, and it wont hurt if they are bigger, as long as RELOC + 8*SIZE
27 * is less than 0xa0000.
28 *
29 * This bootblock does not support fdisk partitions, and can only be used
30 * as the master boot block.
31 *
78ed81a3 32 * from: 386BSD 0.1
33 * $Id$
15637ed4
RG
34 */
35
36#include "param.h"
37#include "disklabel.h"
38#include "i386/isa/asreg.h"
39
40/* RELOC should be defined with a -D flag to cc */
41
42#define SECOND_LEVEL_BOOT_START (RELOC + 0x400)
43#define READ_SIZE 8192
44
45#define as_port 0x330
46#define target 0
47
48
49#define NBLOCKS (READ_SIZE / 512) /* how many logical blocks to read */
50
51
52/* These are the parameters to pass to the second level boot */
53#define dev 4 /* major device number of as driver in
54 i386/stand/conf.c and i386/i386/conf.c */
55#define unit 0 /* partition number of root file system */
56#define off 0 /* block offset of root file system */
57
58/* inline i/o borrowed from Roell X server */
59static __inline__ void
60outb(port, val)
61short port;
62char val;
63{
64 __asm__ volatile("outb %%al, %1" : :"a" (val), "d" (port));
65}
66
67static __inline__ unsigned int
68inb(port)
69short port;
70{
71 unsigned int ret;
72 __asm__ volatile("xorl %%eax, %%eax; inb %1, %%al"
73 : "=a" (ret) : "d" (port));
74 return ret;
75}
76
77/* this code is linked at 0x7c00 and is loaded there by the BIOS */
78
79asm ("
80 /* we're running in 16 real mode, so normal assembly doesn't work */
81bootbase:
82 /* interrupts off */
83 cli
84
85 /* load gdt */
86 .byte 0x2e,0x0f,0x01,0x16 /* lgdt %cs:$imm */
87 .word _gdtarg + 2
88
89 /* turn on protected mode */
90 smsw %ax
91 orb $1,%al
92 lmsw %ax
93
94 /* flush prefetch queue and reload %cs */
95 .byte 0xea /* ljmp $8, flush */
96 .word flush
97 .word 8
98
99flush:
100 /* now running in 32 bit mode */
101 movl $0x10,%eax
102 movl %ax,%ds
103 movl %ax,%es
104 movl %ax,%ss
105 movl $0x7c00,%esp
106 call _main
107"); /* end of asm */
108
109const char gdt[] = {
110 0, 0, 0, 0, 0, 0, 0, 0,
111 0xff, 0xff, 0, 0, 0, 0x9f, 0xcf, 0, /* code segment */
112 0xff, 0xff, 0, 0, 0, 0x93, 0xcf, 0, /* data segment */
113};
114
115const struct {
116 short filler;
117 short size;
118 const char *gdt;
119} gdtarg = { 0, sizeof gdt - 1, gdt };
120
121#define CRTBASE ((char *)0xb8000)
122#define CHECKPOINT(x) (CRTBASE[0] = x)
123
124volatile struct mailbox_entry mailbox[2];
125const char ccb[] = {
126 0, /* opcode: normal read/write */
127 (target << 5) | 8, /* target num and read flag */
128 10, /* scsi cmd len */
129 1, /* no automatic request for sense */
130 READ_SIZE >> 16, /* data length */
131 READ_SIZE >> 8,
132 READ_SIZE,
133 RELOC >> 16, /* data pointer */
134 RELOC >> 8,
135 RELOC,
136 0, 0, 0, /* link pointer */
137 0, /* link id */
138 0, /* host status */
139 0, /* target status */
140 0, 0, /* reserved */
141
142 /* scsi cdb */
143 0x28, /* read opcode */
144 0, /* logical unit number */
145 0, 0, 0, 0, /* logical block address */
146 0, /* reserved */
147 0, NBLOCKS, /* transfer length */
148 0, /* link control */
149};
150
151int (*f)();
152
153main ()
154{
155 int i;
156 extern char edata[], end[];
157 char volatile * volatile p, *q;
158 int physaddr;
159
160 CHECKPOINT ('a');
161
162 /* clear bss */
163 for (p = edata; p < end; p++)
164 *p = 0;
165
166 f = (int (*)())SECOND_LEVEL_BOOT_START;
167
168 /* dma setup: see page 5-31 in the Adaptech manual */
169 /* this knows we are using drq 5 */
170 outb (0xd6, 0xc1);
171 outb (0xd4, 0x01);
172
173 outb (as_port + AS_CONTROL, AS_CONTROL_SRST);
174
175 /* delay a little */
176 inb (0x84);
177
178 while (inb (as_port + AS_STATUS) != (AS_STATUS_INIT | AS_STATUS_IDLE))
179 ;
180
181 CHECKPOINT ('b');
182
183 as_put_byte (AS_CMD_MAILBOX_INIT);
184 as_put_byte (1); /* one mailbox out, one in */
185 as_put_byte ((int)mailbox >> 16);
186 as_put_byte ((int)mailbox >> 8);
187 as_put_byte ((int)mailbox);
188
189 while (inb (as_port + AS_STATUS) & AS_STATUS_INIT)
190 ;
191
192 CHECKPOINT ('c');
193
194 mailbox[0].msb = (int)ccb >> 16;
195 mailbox[0].mid = (int)ccb >> 8;
196 mailbox[0].lsb = (int)ccb;
197 mailbox[0].cmd = 1;
198
199 as_put_byte (AS_CMD_START_SCSI_COMMAND);
200
201 /* wait for done */
202 while (mailbox[1].cmd == 0)
203 ;
204
205 CHECKPOINT ('d');
206
207 if (mailbox[1].cmd != 1) {
208 /* some error */
209 CHECKPOINT ('X');
210 while (1);
211 }
212
213 CHECKPOINT ('e');
214
215 /* the optimazation that gcc uses when it knows we are jumpping
216 * to a constant address is broken, so we have to use a variable
217 * here
218 */
219 (*f)(dev, unit, off);
220}
221
222int
223as_put_byte (val)
224int val;
225{
226 while (inb (as_port + AS_STATUS) & AS_STATUS_CDF)
227 ;
228 outb (as_port + AS_DATA_OUT, val);
229}
230
231asm ("
232ebootblkcode:
233 . = 510
234 .byte 0x55
235 .byte 0xaa
236ebootblk: /* MUST BE EXACTLY 0x200 BIG FOR SURE */
237");