|
|
1.1 root 1: /*
2: * sys/i386/stand/asbootblk.c
3: *
4: * Boot block for Adaptech 1542 SCSI
5: *
6: * April 10, 1992
7: * Pace Willisson
8: * [email protected]
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: */
32:
33: #include "param.h"
34: #include "disklabel.h"
35: #include "i386/isa/asreg.h"
36:
37: /* RELOC should be defined with a -D flag to cc */
38:
39: #define SECOND_LEVEL_BOOT_START (RELOC + 0x400)
40: #define READ_SIZE 8192
41:
42: #define as_port 0x330
43: #define target 0
44:
45:
46: #define NBLOCKS (READ_SIZE / 512) /* how many logical blocks to read */
47:
48:
49: /* These are the parameters to pass to the second level boot */
50: #define dev 4 /* major device number of as driver in
51: i386/stand/conf.c and i386/i386/conf.c */
52: #define unit 0 /* partition number of root file system */
53: #define off 0 /* block offset of root file system */
54:
55: /* inline i/o borrowed from Roell X server */
56: static __inline__ void
57: outb(port, val)
58: short port;
59: char val;
60: {
61: __asm__ volatile("outb %%al, %1" : :"a" (val), "d" (port));
62: }
63:
64: static __inline__ unsigned int
65: inb(port)
66: short port;
67: {
68: unsigned int ret;
69: __asm__ volatile("xorl %%eax, %%eax; inb %1, %%al"
70: : "=a" (ret) : "d" (port));
71: return ret;
72: }
73:
74: /* this code is linked at 0x7c00 and is loaded there by the BIOS */
75:
76: asm ("
77: /* we're running in 16 real mode, so normal assembly doesn't work */
78: bootbase:
79: /* interrupts off */
80: cli
81:
82: /* load gdt */
83: .byte 0x2e,0x0f,0x01,0x16 /* lgdt %cs:$imm */
84: .word _gdtarg + 2
85:
86: /* turn on protected mode */
87: smsw %ax
88: orb $1,%al
89: lmsw %ax
90:
91: /* flush prefetch queue and reload %cs */
92: .byte 0xea /* ljmp $8, flush */
93: .word flush
94: .word 8
95:
96: flush:
97: /* now running in 32 bit mode */
98: movl $0x10,%eax
99: movl %ax,%ds
100: movl %ax,%es
101: movl %ax,%ss
102: movl $0x7c00,%esp
103: call _main
104: "); /* end of asm */
105:
106: const char gdt[] = {
107: 0, 0, 0, 0, 0, 0, 0, 0,
108: 0xff, 0xff, 0, 0, 0, 0x9f, 0xcf, 0, /* code segment */
109: 0xff, 0xff, 0, 0, 0, 0x93, 0xcf, 0, /* data segment */
110: };
111:
112: const struct {
113: short filler;
114: short size;
115: const char *gdt;
116: } gdtarg = { 0, sizeof gdt - 1, gdt };
117:
118: #define CRTBASE ((char *)0xb8000)
119: #define CHECKPOINT(x) (CRTBASE[0] = x)
120:
121: volatile struct mailbox_entry mailbox[2];
122: const char ccb[] = {
123: 3, /* opcode: normal read/write */
124: (target << 5) | 8, /* target num and read flag */
125: 10, /* scsi cmd len */
126: 1, /* no automatic request for sense */
127: READ_SIZE >> 16, /* data length */
128: READ_SIZE >> 8,
129: READ_SIZE,
130: RELOC >> 16, /* data pointer */
131: RELOC >> 8,
132: RELOC,
133: 0, 0, 0, /* link pointer */
134: 0, /* link id */
135: 0, /* host status */
136: 0, /* target status */
137: 0, 0, /* reserved */
138:
139: /* scsi cdb */
140: 0x28, /* read opcode */
141: 0, /* logical unit number */
142: 0, 0, 0, 0, /* logical block address */
143: 0, /* reserved */
144: 0, NBLOCKS, /* transfer length */
145: 0, /* link control */
146: };
147:
148: int (*f)();
149:
150: main ()
151: {
152: int i;
153: extern char edata[], end[];
154: char volatile * volatile p, *q;
155: int physaddr;
156:
157: CHECKPOINT ('a');
158:
159: /* clear bss */
160: for (p = edata; p < end; p++)
161: *p = 0;
162:
163: f = (int (*)())SECOND_LEVEL_BOOT_START;
164:
165: /* dma setup: see page 5-31 in the Adaptech manual */
166: /* this knows we are using drq 5 */
167: outb (0xd6, 0xc1);
168: outb (0xd4, 0x01);
169:
170: outb (as_port + AS_CONTROL, AS_CONTROL_SRST);
171:
172: /* delay a little */
173: inb (0x84);
174:
175: while (inb (as_port + AS_STATUS) != (AS_STATUS_INIT | AS_STATUS_IDLE))
176: ;
177:
178: CHECKPOINT ('b');
179:
180: as_put_byte (AS_CMD_MAILBOX_INIT);
181: as_put_byte (1); /* one mailbox out, one in */
182: as_put_byte ((int)mailbox >> 16);
183: as_put_byte ((int)mailbox >> 8);
184: as_put_byte ((int)mailbox);
185:
186: while (inb (as_port + AS_STATUS) & AS_STATUS_INIT)
187: ;
188:
189: CHECKPOINT ('c');
190:
191: mailbox[0].msb = (int)ccb >> 16;
192: mailbox[0].mid = (int)ccb >> 8;
193: mailbox[0].lsb = (int)ccb;
194: mailbox[0].cmd = 1;
195:
196: as_put_byte (AS_CMD_START_SCSI_COMMAND);
197:
198: /* wait for done */
199: while (mailbox[1].cmd == 0)
200: ;
201:
202: CHECKPOINT ('d');
203:
204: if (mailbox[1].cmd != 1) {
205: /* some error */
206: CHECKPOINT ('X');
207: while (1);
208: }
209:
210: CHECKPOINT ('e');
211:
212: /* the optimazation that gcc uses when it knows we are jumpping
213: * to a constant address is broken, so we have to use a variable
214: * here
215: */
216: (*f)(dev, unit, off);
217: }
218:
219: int
220: as_put_byte (val)
221: int val;
222: {
223: while (inb (as_port + AS_STATUS) & AS_STATUS_CDF)
224: ;
225: outb (as_port + AS_DATA_OUT, val);
226: }
227:
228: asm ("
229: ebootblkcode:
230: . = 510
231: .byte 0x55
232: .byte 0xaa
233: ebootblk: /* MUST BE EXACTLY 0x200 BIG FOR SURE */
234: ");
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.