summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>1996-10-29 13:27:30 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>1996-10-29 13:27:30 +0000
commit02a3735563a35883698e629c27116346426b52f1 (patch)
treeda67eb70c3b0f1e998429c38a13687066dd9f6d9 /sys
parent0d07f2cca9a5c81fac809c79f5e46c454dd35416 (diff)
removed by accident
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/i386/stand/as.c269
-rw-r--r--sys/arch/i386/stand/asbootblk.c236
2 files changed, 505 insertions, 0 deletions
diff --git a/sys/arch/i386/stand/as.c b/sys/arch/i386/stand/as.c
new file mode 100644
index 00000000000..796b2650378
--- /dev/null
+++ b/sys/arch/i386/stand/as.c
@@ -0,0 +1,269 @@
+/* $NetBSD: as.c,v 1.4 1994/10/27 04:21:45 cgd Exp $ */
+
+/*
+ * sys/i386/stand/as.c
+ *
+ * Standalone driver for Adaptech 1542 SCSI
+ *
+ * Pace Willisson pace@blitz.com April 8, 1992
+ */
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <dev/isa/ahareg.h>
+#include "saio.h"
+
+#ifdef ASDEBUG
+#define ASPRINT(x) { printf x; DELAY (10000); }
+#else
+#define ASPRINT(x)
+#endif
+
+#define NRETRIES 3
+
+int as_port = 0x330;
+
+struct mailbox_entry mailbox[2];
+
+int
+asopen(io)
+struct iob *io;
+{
+ struct disklabel *dd;
+ char cdb[6];
+ char data[12];
+ int val;
+ int oval;
+ int i;
+ struct iob aio;
+
+ if (io->i_unit < 0 || io->i_unit > 8
+ || io->i_part < 0 || io->i_part > 8
+ || io->i_ctlr < 0 || io->i_ctlr > 0)
+ return (-1);
+
+ /* dma setup: see page 5-31 in the Adaptech manual */
+ outb (0xd6, 0xc1);
+ outb (0xd4, 0x01);
+
+ ASPRINT (("resetting adaptech card... "));
+
+ outb (as_port + AS_CONTROL, AS_CONTROL_SRST);
+
+ /* delay a little */
+ for (i = 0; i < 100; i++)
+ inb (0x84);
+
+ while (inb (as_port + AS_STATUS) != (AS_STATUS_INIT | AS_STATUS_IDLE))
+ ;
+
+ ASPRINT (("reset ok "));
+
+ 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)
+ ;
+
+ ASPRINT (("mailbox init ok "));
+
+ /* do mode select to set the logical block size */
+ bzero (cdb, 6);
+ cdb[0] = 0x15; /* MODE SELECT */
+ cdb[4] = 12; /* parameter list length */
+
+ bzero (data, 12);
+ data[3] = 8; /* block descriptor length */
+ data[9] = DEV_BSIZE >> 16;
+ data[10] = DEV_BSIZE >> 8;
+ data[11] = DEV_BSIZE;
+
+ if (ascmd (io->i_unit, 0, cdb, 6, data, 12, 1) < 0) {
+ printf ("as%d: error setting logical block size\n",
+ io->i_unit);
+ return (-1);
+ }
+
+ aio = *io;
+ aio.i_bn = LABELSECTOR;
+ aio.i_cc = DEV_BSIZE;
+ /*io->i_ma = buf;*/
+ aio.i_boff = 0;
+
+#ifdef was
+ if (asstrategy (&aio, F_READ) == DEV_BSIZE) {
+ dd = (struct disklabel *)aio.i_ma;
+ io->i_boff = dd->d_partitions[io->i_part].p_offset;
+ ASPRINT (("partition offset %d ", io->i_boff));
+ }
+#else
+{
+extern struct disklabel disklabel;
+ io->i_boff = disklabel.d_partitions[io->i_part].p_offset;
+ ASPRINT (("partition offset %d ", io->i_boff));
+}
+#endif
+
+ ASPRINT (("asopen ok "));
+ return(0);
+}
+
+/* func is F_WRITE or F_READ
+ * io->i_unit, io->i_part, io->i_bn is starting block
+ * io->i_cc is byte count
+ * io->i_ma is memory address
+ * io->i_boff is block offset for this partition (set up in asopen)
+ */
+int
+asstrategy(io, func)
+struct iob *io;
+{
+ char cdb[6];
+ int blkno;
+ int retry;
+
+ ASPRINT (("asstrategy(target=%d, block=%d+%d, count=%d) ",
+ io->i_unit, io->i_bn, io->i_boff, io->i_cc));
+
+ if (func == F_WRITE) {
+ printf ("as%d: write not supported\n", io->i_unit);
+ return (0);
+ }
+
+ if (io->i_cc == 0)
+ return (0);
+
+ if (io->i_cc % DEV_BSIZE != 0) {
+ printf ("as%d: transfer size not multiple of %d\n",
+ io->i_unit, DEV_BSIZE);
+ return (0);
+ }
+
+ /* retry in case we get a unit-attention error, which just
+ * means the drive has been reset since the last command
+ */
+ for (retry = 0; retry < NRETRIES; retry++) {
+ blkno = io->i_bn + io->i_boff;
+
+ cdb[0] = 8; /* scsi read opcode */
+ cdb[1] = (blkno >> 16) & 0x1f;
+ cdb[2] = blkno >> 8;
+ cdb[3] = blkno;
+ cdb[4] = io->i_cc / DEV_BSIZE;
+ cdb[5] = 0; /* control byte (used in linking) */
+
+ if (ascmd (io->i_unit, 1, cdb, 6, io->i_ma, io->i_cc,
+ retry == NRETRIES - 1) >= 0) {
+ ASPRINT (("asstrategy ok "));
+ return (io->i_cc);
+ }
+ }
+
+ ASPRINT (("asstrategy failed "));
+ return (0);
+}
+
+int
+ascmd (target, readflag, cdb, cdblen, data, datalen, printerr)
+int target;
+int readflag;
+char *cdb;
+int cdblen;
+char *data;
+int datalen;
+int printerr;
+{
+ struct ccb ccb;
+ int physaddr;
+ unsigned char *sp;
+ int i;
+
+ if (mailbox[0].cmd != 0)
+ /* this can't happen, unless the card flakes */
+ _stop ("asstart: mailbox not available\n");
+
+ bzero (&ccb, sizeof ccb);
+
+ ccb.ccb_opcode = 0;
+ ccb.ccb_addr_and_control = target << 5;
+ if (datalen != 0)
+ ccb.ccb_addr_and_control |= readflag ? 8 : 0x10;
+ else
+ ccb.ccb_addr_and_control |= 0x18;
+
+ ccb.ccb_data_len_msb = datalen >> 16;
+ ccb.ccb_data_len_mid = datalen >> 8;
+ ccb.ccb_data_len_lsb = datalen;
+
+ ccb.ccb_requst_sense_allocation_len = MAXSENSE;
+
+ physaddr = (int)data;
+ ccb.ccb_data_ptr_msb = physaddr >> 16;
+ ccb.ccb_data_ptr_mid = physaddr >> 8;
+ ccb.ccb_data_ptr_lsb = physaddr;
+
+ ccb.ccb_scsi_command_len = cdblen;
+ bcopy (cdb, ccb.ccb_cdb, cdblen);
+
+#ifdef ASDEBUG
+ printf ("ccb: ");
+ for (i = 0; i < 48; i++)
+ printf ("%x ", ((unsigned char *)&ccb)[i]);
+ printf ("\n");
+ /*getchar ();*/
+#endif
+
+ physaddr = (int)&ccb;
+ mailbox[0].msb = physaddr >> 16;
+ mailbox[0].mid = physaddr >> 8;
+ mailbox[0].lsb = physaddr;
+ mailbox[0].cmd = 1;
+
+ /* tell controller to look in its mailbox */
+ outb (as_port + AS_CONTROL, AS_CONTROL_IRST);
+ as_put_byte (AS_CMD_START_SCSI_COMMAND);
+
+ /* wait for status */
+ ASPRINT (("waiting for status..."));
+ while (mailbox[1].cmd == 0)
+ ;
+ mailbox[1].cmd = 0;
+
+
+ if (ccb.ccb_host_status != 0 || ccb.ccb_target_status != 0) {
+#ifdef ASDEBUG
+ printerr = 1;
+#endif
+ if (printerr) {
+ printf ("as%d error: hst=%x tst=%x sense=",
+ target,
+ ccb.ccb_host_status,
+ ccb.ccb_target_status);
+ sp = ccb_sense (&ccb);
+ for (i = 0; i < 8; i++)
+ printf ("%x ", sp[i]);
+ printf ("\n");
+#ifdef ASDEBUG
+ /*getchar ();*/
+#endif
+ }
+ return (-1);
+ }
+
+ ASPRINT (("ascmd ok "));
+
+ return (0);
+}
+
+int
+as_put_byte (val)
+int val;
+{
+ while (inb (as_port + AS_STATUS) & AS_STATUS_CDF)
+ ;
+ outb (as_port + AS_DATA_OUT, val);
+}
+
diff --git a/sys/arch/i386/stand/asbootblk.c b/sys/arch/i386/stand/asbootblk.c
new file mode 100644
index 00000000000..f3ea79c233c
--- /dev/null
+++ b/sys/arch/i386/stand/asbootblk.c
@@ -0,0 +1,236 @@
+/* $NetBSD: asbootblk.c,v 1.4 1994/10/27 04:21:46 cgd Exp $ */
+
+/*
+ * 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 <sys/param.h>
+#include <sys/disklabel.h>
+#include <dev/isa/ahareg.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[] = {
+ 0, /* 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 */
+");