* sys/i386/stand/asbootblk.c
* Boot block for Adaptech 1542 SCSI
* Placed in the public domain with NO WARRANTIES, not even the
* implied warranties for MERCHANTABILITY or FITNESS FOR A
* cc -O -c -DRELOC=0x70000 asbootblk.c
* ld -N -T 7c00 asbootblk.o
* This should result in a file with 512 bytes of text and no initialized
* data. Strip the 32 bit header and place in block 0.
* When run, this program copies at least the first 8 blocks of SCSI
* target 0 to the address specified by RELOC, then jumps to the
* address RELOC+1024 (skipping the boot block and disk label). Usually,
* disks have 512 bytes per block, but I don't think they ever have
* less, and it wont hurt if they are bigger, as long as RELOC + 8*SIZE
* This bootblock does not support fdisk partitions, and can only be used
* as the master boot block.
#include "i386/isa/asreg.h"
/* RELOC should be defined with a -D flag to cc */
#define SECOND_LEVEL_BOOT_START (RELOC + 0x400)
#define NBLOCKS (READ_SIZE / 512) /* how many logical blocks to read */
/* These are the parameters to pass to the second level boot */
#define dev 4 /* major device number of as driver in
i386/stand/conf.c and i386/i386/conf.c */
#define unit 0 /* partition number of root file system */
#define off 0 /* block offset of root file system */
/* inline i/o borrowed from Roell X server */
__asm__
volatile("outb %%al, %1" : :"a" (val
), "d" (port
));
static __inline__
unsigned int
__asm__
volatile("xorl %%eax, %%eax; inb %1, %%al"
: "=a" (ret
) : "d" (port
));
/* this code is linked at 0x7c00 and is loaded there by the BIOS */
/* we're running in 16 real mode, so normal assembly doesn't work */
.byte 0x2e,0x0f,0x01,0x16 /* lgdt %cs:$imm */
/* turn on protected mode */
/* flush prefetch queue and reload %cs */
.byte 0xea /* ljmp $8, flush */
/* now running in 32 bit mode */
0xff, 0xff, 0, 0, 0, 0x9f, 0xcf, 0, /* code segment */
0xff, 0xff, 0, 0, 0, 0x93, 0xcf, 0, /* data segment */
} gdtarg
= { 0, sizeof gdt
- 1, gdt
};
#define CRTBASE ((char *)0xb8000)
#define CHECKPOINT(x) (CRTBASE[0] = x)
volatile struct mailbox_entry mailbox
[2];
3, /* opcode: normal read/write */
(target
<< 5) | 8, /* target num and read flag */
1, /* no automatic request for sense */
READ_SIZE
>> 16, /* data length */
RELOC
>> 16, /* data pointer */
0, 0, 0, /* link pointer */
0, /* logical unit number */
0, 0, 0, 0, /* logical block address */
0, NBLOCKS
, /* transfer length */
extern char edata
[], end
[];
char volatile * volatile p
, *q
;
for (p
= edata
; p
< end
; p
++)
f
= (int (*)())SECOND_LEVEL_BOOT_START
;
/* dma setup: see page 5-31 in the Adaptech manual */
/* this knows we are using drq 5 */
outb (as_port
+ AS_CONTROL
, AS_CONTROL_SRST
);
while (inb (as_port
+ AS_STATUS
) != (AS_STATUS_INIT
| AS_STATUS_IDLE
))
as_put_byte (AS_CMD_MAILBOX_INIT
);
as_put_byte (1); /* one mailbox out, one in */
as_put_byte ((int)mailbox
>> 16);
as_put_byte ((int)mailbox
>> 8);
as_put_byte ((int)mailbox
);
while (inb (as_port
+ AS_STATUS
) & AS_STATUS_INIT
)
mailbox
[0].msb
= (int)ccb
>> 16;
mailbox
[0].mid
= (int)ccb
>> 8;
mailbox
[0].lsb
= (int)ccb
;
as_put_byte (AS_CMD_START_SCSI_COMMAND
);
while (mailbox
[1].cmd
== 0)
if (mailbox
[1].cmd
!= 1) {
/* the optimazation that gcc uses when it knows we are jumpping
* to a constant address is broken, so we have to use a variable
while (inb (as_port
+ AS_STATUS
) & AS_STATUS_CDF
)
outb (as_port
+ AS_DATA_OUT
, val
);
ebootblk: /* MUST BE EXACTLY 0x200 BIG FOR SURE */