386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Thu, 25 Jun 1992 22:09:41 +0000 (14:09 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Thu, 25 Jun 1992 22:09:41 +0000 (14:09 -0800)
Work on file usr/src/sys.386bsd/i386/stand/asbootblk.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/src/sys.386bsd/i386/stand/asbootblk.c [new file with mode: 0644]

diff --git a/usr/src/sys.386bsd/i386/stand/asbootblk.c b/usr/src/sys.386bsd/i386/stand/asbootblk.c
new file mode 100644 (file)
index 0000000..1062a42
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * sys/i386/stand/asbootblk.c
+ *
+ * Boot block for Adaptech 1542 SCSI
+ *
+ * April 10, 1992
+ * Pace Willisson
+ * pace@blitz.com
+ *
+ * Placed in the public domain with NO WARRANTIES, not even the
+ * implied warranties for MERCHANTABILITY or FITNESS FOR A 
+ * PARTICULAR PURPOSE.
+ *
+ * To compile:
+ *
+ *     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
+ * is less than 0xa0000.
+ *
+ * This bootblock does not support fdisk partitions, and can only be used
+ * as the master boot block.
+ */
+
+#include "param.h"
+#include "disklabel.h"
+#include "i386/isa/asreg.h"
+
+/* RELOC should be defined with a -D flag to cc */
+
+#define SECOND_LEVEL_BOOT_START (RELOC + 0x400)
+#define READ_SIZE 8192
+
+#define as_port 0x330
+#define target 0
+
+
+#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 */
+static __inline__ void
+outb(port, val)
+short port;
+char val;
+{
+   __asm__ volatile("outb %%al, %1" : :"a" (val), "d" (port));
+}
+
+static __inline__ unsigned int
+inb(port)
+short port;
+{
+   unsigned int ret;
+   __asm__ volatile("xorl %%eax, %%eax; inb %1, %%al"
+                   : "=a" (ret) : "d" (port));
+   return ret;
+}
+
+/* this code is linked at 0x7c00 and is loaded there by the BIOS */
+
+asm ("
+       /* we're running in 16 real mode, so normal assembly doesn't work */
+bootbase:
+       /* interrupts off */
+       cli
+
+       /* load gdt */
+       .byte 0x2e,0x0f,0x01,0x16 /* lgdt %cs:$imm */
+       .word _gdtarg + 2
+
+       /* turn on protected mode */
+       smsw    %ax
+       orb     $1,%al
+       lmsw    %ax
+
+       /* flush prefetch queue and reload %cs */
+       .byte 0xea /* ljmp $8, flush */
+       .word flush
+       .word 8
+
+flush:
+       /* now running in 32 bit mode */
+       movl    $0x10,%eax
+       movl    %ax,%ds
+       movl    %ax,%es
+       movl    %ax,%ss
+       movl    $0x7c00,%esp
+       call    _main
+"); /* end of asm */
+
+const char gdt[] = {
+       0, 0, 0, 0, 0, 0, 0, 0,
+       0xff, 0xff, 0, 0, 0, 0x9f, 0xcf, 0, /* code segment */
+       0xff, 0xff, 0, 0, 0, 0x93, 0xcf, 0, /* data segment */
+};
+
+const struct {
+       short filler;
+       short size;
+       const char *gdt;
+} gdtarg = { 0, sizeof gdt - 1, gdt };
+
+#define CRTBASE ((char *)0xb8000)
+#define CHECKPOINT(x) (CRTBASE[0] = x)
+
+volatile struct mailbox_entry mailbox[2];
+const char ccb[] = {
+       3, /* opcode: normal read/write */
+       (target << 5) | 8, /* target num and read flag */
+       10, /* scsi cmd len */
+       1, /* no automatic request for sense */
+       READ_SIZE >> 16, /* data length */
+       READ_SIZE >> 8,
+       READ_SIZE,
+       RELOC >> 16, /* data pointer */
+       RELOC >> 8,
+       RELOC,
+       0, 0, 0, /* link pointer */
+       0, /* link id */
+       0, /* host status */
+       0, /* target status */
+       0, 0, /* reserved */
+
+       /* scsi cdb */
+       0x28, /* read opcode */
+       0, /* logical unit number */
+       0, 0, 0, 0, /* logical block address */
+       0,      /* reserved */
+       0, NBLOCKS, /* transfer length */
+       0, /* link control */
+};
+
+int (*f)();
+
+main ()
+{
+       int i;
+       extern char edata[], end[];
+       char volatile * volatile p, *q;
+       int physaddr;
+
+       CHECKPOINT ('a');
+
+       /* clear bss */
+       for (p = edata; p < end; p++)
+               *p = 0;
+
+       f = (int (*)())SECOND_LEVEL_BOOT_START;
+
+       /* dma setup: see page 5-31 in the Adaptech manual */
+       /* this knows we are using drq 5 */
+       outb (0xd6, 0xc1);
+       outb (0xd4, 0x01);
+
+       outb (as_port + AS_CONTROL, AS_CONTROL_SRST);
+
+       /* delay a little */
+       inb (0x84);
+       
+       while (inb (as_port + AS_STATUS) != (AS_STATUS_INIT | AS_STATUS_IDLE))
+               ;
+
+       CHECKPOINT ('b');
+
+       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)
+               ;
+
+       CHECKPOINT ('c');
+
+       mailbox[0].msb = (int)ccb >> 16;
+       mailbox[0].mid = (int)ccb >> 8;
+       mailbox[0].lsb = (int)ccb;
+       mailbox[0].cmd = 1;
+
+       as_put_byte (AS_CMD_START_SCSI_COMMAND);
+
+       /* wait for done */
+       while (mailbox[1].cmd == 0)
+               ;
+
+       CHECKPOINT ('d');
+
+       if (mailbox[1].cmd != 1) {
+               /* some error */
+               CHECKPOINT ('X');
+               while (1);
+       }
+
+       CHECKPOINT ('e');
+
+       /* the optimazation that gcc uses when it knows we are jumpping
+        * to a constant address is broken, so we have to use a variable 
+        * here
+        */
+       (*f)(dev, unit, off);
+}
+
+int
+as_put_byte (val)
+int val;
+{
+       while (inb (as_port + AS_STATUS) & AS_STATUS_CDF)
+               ;
+       outb (as_port + AS_DATA_OUT, val);
+}
+
+asm ("
+ebootblkcode:
+       . = 510
+       .byte 0x55
+       .byte 0xaa
+ebootblk:                      /* MUST BE EXACTLY 0x200 BIG FOR SURE */
+");